以下源文件将无法使用 MSVC 编译器 (v15.00.30729.01) 进行编译:
/* stest.c */
#ifdef __cplusplus
extern "C" {
#endif
struct Test;
/* NB: This may be extern when imported by another module. */
struct Test make_Test(int x);
struct Test { int x; };
struct Test make_Test(int x)
{
struct Test r;
r.x = x;
return r;
}
#ifdef __cplusplus
}
#endif
编译cl /c /Tpstest.c
产生以下错误:
stest.c(8) : error C2526: 'make_Test' : C linkage function cannot return C++ class 'Test'
stest.c(6) : see declaration of 'Test'
不编译/Tp
(告诉cl
将文件视为 C++)工作正常。该文件还可以在 C 和 C++ 模式下在 DigitalMars C 和 GCC(来自 mingw)中正常编译。我也-ansi -pedantic -Wall
与 GCC 一起使用,它没有任何抱怨。
由于我将在下面讨论的原因,我们需要将此文件编译为 MSVC 的 C++(而不是其他文件),但函数被编译为 C。本质上,我们想要一个普通的 C 编译器......除了大约六行. 是否有一个开关或属性或我可以添加的东西可以让它工作?
有问题的代码(虽然不是上面的;这只是一个简化的例子)是由代码生成器生成的。
作为其中的一部分,我们需要能够生成浮点 nan 和无穷大作为常量(长话短说),这意味着我们必须在 C++ 模式下使用 MSVC 编译才能真正做到这一点。我们只找到了一种可行的解决方案,而且它只适用于 C++ 模式。
我们包装代码是extern "C" {...}
因为我们想要控制修改和调用约定,以便我们可以与现有的 C 代码交互。...也因为我信任 C++ 编译器,就我可以扔一个小百货商店。我也尝试将行仅包含reinterpret_cast
在 中extern "C++" {...}
,但这当然行不通。遗憾。
我发现了一个潜在的解决方案,它需要重新排序声明,以便完整的结构定义出现在函数 foward decl 之前,但是由于 codegen 的执行方式,这非常不方便,所以我真的很想避免不得不如果可以的话,沿着那条路走下去。