如何在纯C和CUDA C文件之间包含头文件?

3

我需要从一个C语言函数main()(位于main.c中)中调用位于gpu.cu中的CUDA C函数foo()。我尝试了以下代码:

  • main.c (caller):

    #include "gpu.h"
    int main();
    int main() { foo(); }
    
  • gpu.h (foo() declaration): <--- problem here

    extern void foo();
    
  • gpu.cu (foo() definition):

    #include "gpu.h"
    extern "C" void foo() { ... }
    
  • I get the error:

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

然而,如果不使用头文件,以下内容仍然可以正常工作:

  • main.c (caller):

    void foo();
    int main();
    int main() { foo(); }
    
  • gpu.cu (foo() declaration and definition):

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

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

我正在使用 NVCC 编译和链接(即用于纯C和CUDA C代码)。

非常感谢。

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代码,则可能会失败。

如何修复这个问题可能会严重依赖于您的代码实际结构,我猜测它并不像您所描述的那么简单。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接