使用 C++ 中的 C 函数程序-extern关键字问题
我在使用 C++ 程序时遇到问题。我想在 C++ 文件中使用 C 文件中定义的函数。这是我的 C++ 文件代码:
#include <string>
#include <iostream>
#include <stdio.h>
extern void squre_array();
using namespace std;
int main() {
squre_array();
}
现在这是我在其中定义 sqre_array() 的 C 文件代码:
#include <stdio.h>
#include <cuda.h>
__global__ void square_array(float *a, int N)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx<N)
a[idx] = a[idx] * a[idx];
}
void squre_array()
{
float *a_h, *a_d;
const int N = 10;
size_t size = N * sizeof(float);
a_h = (float *)malloc(size);
cudaMalloc((void **) &a_d, size);
for (int i=0; i<N; i++) a_h[i] = (float)i;
cudaMemcpy(a_d, a_h, size, cudaMemcpyHostToDevice);
int block_size = 4;
int n_blocks = N/block_size + (N%block_size == 0 ? 0:1);
square_array <<< n_blocks, block_size >>> (a_d, N);
cudaMemcpy(a_h, a_d, sizeof(float)*N, cudaMemcpyDeviceToHost);
// Print results
for (int i=0; i<N; i++) printf("%d %f\n", i, a_h[i]);
free(a_h);
cudaFree(a_d);
}
现在谁能告诉我如何将此函数链接到我的 C++ 程序? 每次编译程序时,我都会收到错误消息:
cpp:: undefined reference to `squre_array()'
谁能告诉我我做错了什么? 如何将 squre_array()
函数链接到我的 C++ 程序中?
I am having a problem with a C++ program. I want to use a function which is defined in a C file in a C++ file. Here is my code for the C++ file:
#include <string>
#include <iostream>
#include <stdio.h>
extern void squre_array();
using namespace std;
int main() {
squre_array();
}
Now here is the code for the C file in which I defined squre_array()
:
#include <stdio.h>
#include <cuda.h>
__global__ void square_array(float *a, int N)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx<N)
a[idx] = a[idx] * a[idx];
}
void squre_array()
{
float *a_h, *a_d;
const int N = 10;
size_t size = N * sizeof(float);
a_h = (float *)malloc(size);
cudaMalloc((void **) &a_d, size);
for (int i=0; i<N; i++) a_h[i] = (float)i;
cudaMemcpy(a_d, a_h, size, cudaMemcpyHostToDevice);
int block_size = 4;
int n_blocks = N/block_size + (N%block_size == 0 ? 0:1);
square_array <<< n_blocks, block_size >>> (a_d, N);
cudaMemcpy(a_h, a_d, sizeof(float)*N, cudaMemcpyDeviceToHost);
// Print results
for (int i=0; i<N; i++) printf("%d %f\n", i, a_h[i]);
free(a_h);
cudaFree(a_d);
}
Now can any one tell me how to link this function to my C++ program?
Every time I compile the program, I got the error message:
cpp:: undefined reference to `squre_array()'
Can anyone tell me what I was doing wrong?
How can I link the squre_array()
function into my C++ program?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在 C++ 代码中,您需要将 C 函数声明为 extern "C"
In the C++ code you need to declare the C function as extern "C"
在代码片段的第一行之前,添加三行:
<代码>
在代码片段的最后一行之后,添加三行:
<代码>
魔法?不,只是 C 和 C++ 编译器以不同的格式保存代码的符号;这可以让 C++ 链接器理解代码片段中的 C 符号。
——皮特
Before the first line of your code snippet, add the three lines:
After the final line of your code snippet, add the three lines:
Magic? No, it's only that the C and C++ compilers save your code's symbols in different formats; this lets the C++ linker understand the C symbols in your code snippet.
--pete
在 OP 应用了一些编辑之后,让我们逐步修改 OP 的代码,因为它现在(3 月 17 日东部时间 0600)出现:
步骤 1:
考虑片段 1,它是 C++ int main( ) prog 。链接器将尝试执行您想要的操作,即使 sqre_array() 可从 main() 访问(即可调用)。在此 C++ 文件中,您必须 #include 声明 sqre_array( ) 为 C 语言 函数——整个过程中唯一的关键点,而不是一个 C++ 函数。 (为什么?因为编译器对 C 语言符号的格式和存储方式与 C++ 符号不同;因此当链接器出现时,C 源代码中定义的 C 类型符号不一样 作为 main( ) 中引用的 C++ 类型符号。)现在,该头文件名为 cuda.h 吗?我们假设是这样。请记住,这样的声明会使“extern void sqre_array( )”变得多余且令人困惑,因此请从此源文件中删除该行:
STEP 2:
Now consider snippet 2, which defines the squre_array( ) function. This is plain old C code so we have to bracket all of that C code with two sets of three lines each. These six lines (total) effectively tell the linker that the symbols in the bracketed code are C-type symbols rather than C++-type"munged" symbols. When the linker is finally convinced of that, it can link the squre_array( ) function into your main program:
// insert magic three lines here, way up at the top of your .c file
#ifdef __cplusplus //if we are compiling as C++, tell
extern "C" { //the compiler that this stuff is plain old C
#endif
#include <stdio.h>
#include <cuda.h> <-- remember this "glue" file: we'll change it in step 3
//_全局_ void square_array(float *a, int N) <-- 删除声明,
void square_array(float *a, int N) { <-- 但保留定义
int idx = blockIdx.x * blockDim.x + threadIdx.x;
如果(idx
a[idx] = a[idx] * a[idx];
}
void square_array()
{
浮动*a_h,*a_d;
...
cudaFree(a_d);
}
//关闭魔法三行
#ifdef __cplusplus //
} // 右大括号
#endif
第3步:
OP理解中缺少的重要一点是sqre_array()(和square_array(),如果你想要的话)必须声明;并且该声明需要包含在同一对神奇的三行中。 (OP:为什么一定是这样?)我们在步骤 1 中决定声明将放在 cuda.h 中。或者它可以放入任何 .h 文件中,但无论它在哪里声明,该 .h 文件都必须 #included 在 main( ) 所在的文件中(OP:再说一遍,这是为什么?)。所以让我们修复 cuda.h:
// 再次神奇的三行
#ifdef __cplusplus
外部“C”{
#endif
无效 sqre_array();
void square_array(float *a, int N);
// 关闭魔法三行,就像以前一样
#ifdef __cplusplus //
} // 右大括号
#endif
就是这样。现在您的程序将链接。
——皮特
Step-by-step, let's modify the OP's code as it now (Mar 17 at 0600 eastern) appears, after the OP applied a few edits:
STEP 1:
Consider snippet 1, which is the C++ int main( ) prog. The linker will try to do what you want, which is to make squre_array( ) accessible -- i.e., callable -- from main( ). In this C++ file, you must #include the header file that declares squre_array( ) to be a C-language function -- the one and only crucial point in this whole process -- rather than a C++ function. (Why? Because the compiler formats and stores C-language symbols differently from C++ symbols; and so when the linker comes along, the C-type symbol defined in the C source is not the same as the C++-type symbol referenced in main( ).) Now, is that header file named cuda.h? Let's assume it is. Remember that such a declaration makes "extern void squre_array( )" superfluous and confusing, so take that line out of this source file:
STEP 2:
Now consider snippet 2, which defines the squre_array( ) function. This is plain old C code so we have to bracket all of that C code with two sets of three lines each. These six lines (total) effectively tell the linker that the symbols in the bracketed code are C-type symbols rather than C++-type"munged" symbols. When the linker is finally convinced of that, it can link the squre_array( ) function into your main program:
// insert magic three lines here, way up at the top of your .c file
#ifdef __cplusplus //if we are compiling as C++, tell
extern "C" { //the compiler that this stuff is plain old C
#endif
#include <stdio.h>
#include <cuda.h> <-- remember this "glue" file: we'll change it in step 3
//_global_ void square_array(float *a, int N) <-- remove the declaration,
void square_array(float *a, int N) { <-- but retain the definition
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx
a[idx] = a[idx] * a[idx];
}
void squre_array()
{
float *a_h, *a_d;
...
cudaFree(a_d);
}
// close magic three lines
#ifdef __cplusplus //
} // closing curly bracket
#endif
STEP 3:
The important thing that is missing from the OP's understanding is that squre_array( ) (and square_array( ), if you want) must be declared; and that declaration(s) need to be enclosed within the same pair of magic three lines. (OP: why must that be?) We decided in step 1 that the declaration would go in cuda.h. Or it can go in any .h file, but wherever it's declared, that .h file has to be #included in the file where main( ) resides (OP: again, why is this?). So let's fix up cuda.h:
// magic three lines again
#ifdef __cplusplus
extern "C" {
#endif
void squre_array();
void square_array(float *a, int N);
// close magic three lines, just like before
#ifdef __cplusplus //
} // closing curly bracket
#endif
And that's it. Now your program will link.
-- pete
假设我们有一个函数 F 在 Fh 文件中声明,在 Fc 文件和 main.cpp 中定义,其中 F 被 #included 并调用。你的 C 编译器将 Fh + Fc 编译成目标文件 Fo;然后C++编译器将Fh + main.cpp编译成main.o。然而,C++ 编译器会名称修改,这意味着 Fh 中声明的函数 F 将被编译器重命名为例如F_blah。然后链接器会尝试将main.o和Fo结合起来:它会在main.o中找到对F_blah的调用,但不会找到F_blah的主体,因为C编译器将其编译为F,而不是F_blah。这里我们遇到了未解决的外部符号错误(VS 中的 LNK2001)。对于这样的情况,您需要告诉 C++ 编译器按原样保留函数名称:在 .h 文件中,您在以下块内声明此类函数:
Consider we have a function F declared in a F.h file, defined in a F.c file and a main.cpp, where F is #included and called. Your C compiler compiles F.h + F.c into an object file F.o; then the C++ compiler compiles F.h + main.cpp into main.o. However C++ compilers do name mangling, which means that function F declared in F.h would be renamed by compiler into for example F_blah. Then linker would try to combine main.o and F.o: it will find the call to F_blah in main.o, but it will not find the body of F_blah, because the C compiler compiled it as F, not F_blah. And here we are with the unresolved external symbol error (LNK2001 in VS). For the cases like this you need to tell C++ compiler to keep the name of the function as is: in your .h file you declare such function inside of the following block: