我遇到了C ++程序的问题。我想使用在C ++文件中的C文件中定义的函数。这是我的C ++文件代码:
#include <string>
#include <iostream>
#include <stdio.h>
extern void squre_array();
using namespace std;
int main() {
squre_array();
}
现在这里是我定义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);
}
现在可以告诉我如何将此功能链接到我的C ++程序吗? 每次编译程序时,都会收到错误消息:
cpp:: undefined reference to `squre_array()'
谁能告诉我我做错了什么?
如何将squre_array()
函数链接到我的C ++程序?
答案 0 :(得分:6)
在C ++代码中,您需要将C函数声明为extern“C”
extern "C" void squre_array();
答案 1 :(得分:3)
在代码段的第一行之前,添加以下三行:
#ifdef __cplusplus
extern "C" {
#endif
在代码段的最后一行之后,添加以下三行:
#ifdef __cplusplus
}
#endif
魔术?不,只有C和C ++编译器以不同的格式保存代码的符号;这使得C ++链接器可以理解代码片段中的C符号。
- 皮特
答案 2 :(得分:2)
在OP应用了一些编辑之后,我们一步一步地修改现在的OP代码(3月17日东部0600):
步骤1:
考虑片段1,这是C ++ int main()prog。链接器将尝试执行您想要的操作,即使main()可以访问squre_array(),即可调用。在此C ++文件中,您必须#include 声明 squre_array()的头文件为 C语言 function - 整个过程中唯一的 关键点 - 而不是C ++函数。 (为什么?因为编译器格式化和存储C语言符号与C ++符号不同;因此当链接器出现时,C源中定义的C类型符号 不一样 作为main()中引用的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:
// 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
- 皮特
答案 3 :(得分:0)
考虑我们在F.h文件中声明了一个函数F,它在F.c文件和main.cpp中定义,其中F是#included并被调用。您的C编译器将F.h + F.c编译为目标文件F.o;然后C ++编译器将F.h + main.cpp编译为main.o.但是,C ++编译器执行name mangling,这意味着在F.h中声明的函数F将被编译器重命名为例如F_blah。然后链接器会尝试组合main.o和F.o:它会在main.o中找到对F_blah的调用,但它找不到F_blah的主体,因为C编译器将其编译为F,而不是F_blah。在这里,我们处理未解决的外部符号错误(VS中的LNK2001)。对于这样的情况,你需要告诉C ++编译器保持函数的名称:在.h文件中,你在下面的块中声明了这样的函数:
#ifdef __cplusplus
extern "C" {
#endif
void F();
#ifdef __cplusplus
}
#endif