1

我将 C++ 代码转换为 C,现在我也在尝试更改 Makefile。我有这个:

g++ -fPIC -o bin/linux/release/gpu_md5 cuda_md5.c cuda_md5_cpu.c obj/release/cuda_md5_gpu.cu.o 
-L/usr/local/cuda/lib64 -L../../lib64 
-L../../common/lib64/linux -L/opt/cuda/NVIDIA_CUDA_SDK/lib64 -lcudart     
-L/usr/local/cuda/lib64 -L../../lib64 
-L../../common/lib64/linux -L/opt/cuda/NVIDIA_CUDA_SDK/lib64

据我所知,我可以将 g++ 更改为 gcc,它应该可以正常工作,但事实并非如此。看起来 gcc 无法从 cuda_md5_cpu.c 中找到我在 cuda_md5.c 中调用的函数(PS:我在 cuda_md5.c 中不包括 cuda_md5_cpu.c):

/tmp/ccKdDJiq.o: In function `cuda_compute_md5s':
cuda_md5.c:(.text+0x201): undefined reference to `init_constants'
cuda_md5.c:(.text+0x2e2): undefined reference to `execute_kernel'
collect2: ld returned 1 exit status

怎么了?我刚刚从 g++ 更改为 gcc。

4

1 回答 1

2

我会说很有可能obj/release/cuda_md5_gpu.cu.o(您似乎没有重新编译)已经用 C++ 编译器编译,因此符号名称已通过名称修改进行了修改。

名称修饰是 C++ 编译器使用的一种技术,允许不同的函数具有相同的名称但具有不同的参数类型(重载),而 C 编译器不需要这样做,因为不允许重载。

换句话说,你可能会发现它init_constants(int,float);可能只是被 C 编译器变形为_init_constants,但是,如果你使用 C++ 编译器,你会得到类似的东西_init_constants_$$_IntFloat,以便将它与init_constants(int,double)or区分开来init_constants(void)

因此,试图将 C 编译cuda_md5.c与 C++ 编译链接在一起的链接器obj/release/cuda_md5_gpu.cu.o将无法将函数名称匹配在一起。

这就是您经常extern "C" { ... }在 C++ 代码中看到的原因,它使用 C 规则将函数名称(和其他内容)导出到链接器,以允许将 C 和 C++ 代码链接在一起。

于 2012-10-14T05:33:09.493 回答