[英]Using a C function from a C++ program - extern keyword problem
我在使用C ++程序时遇到问题。 我想使用在C ++文件的C文件中定义的函数。 这是我的C ++文件代码:
#include <string>
#include <iostream>
#include <stdio.h>
extern void squre_array();
using namespace std;
int main() {
squre_array();
}
现在这是我在其中定义squre_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 ++程序中?
在C ++代码中,您需要将C函数声明为extern“ C”
extern "C" void squre_array();
在代码段的第一行之前,添加三行:
#ifdef __cplusplus
extern "C" {
#endif
在代码段的最后一行之后,添加三行:
#ifdef __cplusplus
}
#endif
魔法? 不,只是C和C ++编译器以不同的格式保存代码的符号。 这使C ++链接器可以理解代码段中的C符号。
-皮特
在OP应用了一些编辑后,让我们逐步修改OP的代码,即现在(3月17日,东部0600)出现:
第1步:
考虑片段1,它是C ++ int main()prog。 链接器将尝试执行您想要的操作,即使squre_array()可从main()访问(即可调用)。 在此C ++文件中,您必须#include 声明 squre_array()为C语言函数的头文件,这是整个过程中唯一的关键点 ,而不是C ++函数。 (为什么由于编译器格式和存储的C语言的符号不同于C ++符号;?,所以当接头出现时,在C源代码中定义的C型符号是不一样的C ++ -在主参考型符号( )。)现在,该头文件名为cuda.h吗? 让我们假设它是。 请记住,这样的声明会使“ extern void squre_array()”变得多余和混乱,因此请将该行从源文件中删除:
#include <string>
#include <iostream>
#include <stdio.h>
#include <cuda.h> <-- add this line
//extern void squre_array(); <-- delete this line: we'll declare squre_array( ) in cuda.h
using namespace std;
int main() { squre_array(); }
第2步:
// 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:
// 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
-皮特
考虑一下,我们有一个在Fh文件中声明的函数F(在Fc文件中定义)和一个main.cpp,其中F被包含并调用。 您的C编译器将Fh + Fc编译为目标文件Fo; 然后C ++编译器将Fh + main.cpp编译为main.o。 但是,C ++编译器会命名为mangling ,这意味着在Fh中声明的函数F将被编译器重命名为F_blah。 然后,链接器将尝试将main.o和Fo组合在一起:它将在main.o中找到对F_blah的调用,但找不到F_blah的主体,因为C编译器将其编译为F,而不是F_blah。 在这里,我们面临着无法解决的外部符号错误(VS中为LNK2001)。 对于这种情况,您需要告诉C ++编译器将函数名称保持不变:在.h文件中,您可以在以下代码块中声明该函数:
#ifdef __cplusplus
extern "C" {
#endif
void F();
#ifdef __cplusplus
}
#endif
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.