3

我需要从纯 C函数(位于main.c中)中调用CUDA C函数foo()(位于gpu.cu中)。我的尝试如下所示:main()

  • main.c(调用者):

    #include "gpu.h"
    int main();
    int main() { foo(); }
    
  • gpu.h (foo()声明): <--- 这里有问题

    extern void foo();
    
  • gpu.cufoo()定义):

    #include "gpu.h"
    extern "C" void foo() { ... }
    
  • 我得到错误

    gpu.cu(2): error: linkage specification is incompatible with previous "foo"
    gpu.h(1): here
    

但是,在不使用头文件的情况下,以下操作确实有效:

  • main.c(调用者):

    void foo();
    int main();
    int main() { foo(); }
    
  • gpu.cufoo()声明和定义):

    extern "C" void foo();
    extern "C" void foo() { ... }
    

当然,我更喜欢在纯 C 和 CUDA c 代码中使用单个头文件,那么在头文件中使用的正确语法是什么(extern "C"即使它是 C++ 的东西,我们仍然需要)?我需要 .cuh 扩展名吗?

只使用 NVCC编译和链接(即纯 C 和 CUDA-C 代码)。

非常感谢。

4

1 回答 1

5

你几乎有这个正确的 - 问题在于你如何使用gpu.h. 工具链报告的冲突正在发生,因为其中包含的头文件gpu.cu声明foo()将具有 C++ 链接,但随后定义具有 C 链接。

基本问题是您试图gpu.h同时用作 C 和 C++ 标头。这通常不是一个好主意,但它可以工作。一种方法是确定它是一个 C 头文件并修改 C++ 代码以将其视为一个,所以这样gpu.cu做:

extern "C" {
#include "gpu.h"
}

extern "C" void foo() { ... };

另一种是修改gpu.h,使其行为根据它是被 C 编译器还是 C++ 编译器包含而有所不同,例如:

#ifdef __cplusplus
extern "C" {
#endif
extern void foo();
#ifdef __cplusplus
}
#endif

或者

#ifdef __cplusplus
extern "C" void foo();
#else
void foo();
#endif

将使预处理器发出不同的代码,具体取决于代码是在 C 还是 C++ 环境中编译的。但是,如果您尝试使用 C++ 编译器编译任何名义上的 C 代码,这可能会失败。

您选择如何解决此问题可能在很大程度上取决于代码的真实结构,我猜这并不像您描述的那么简单。

于 2013-01-02T08:05:15.040 回答