我有这个项目,其中包含其他两个项目,它们为同一个 DLL 提供 header 。在一个 header 中,声明被放入命名空间中,而在另一个 header 中则不然。 这对于 GCC 和 MSVC 来说效果很好,但我无法说服 clang 编译它。 所以一个最小的例子是:
x.h:
#include <string>
#if defined __GNUC__
# pragma GCC system_header
#endif // __GNUC__
namespace XX {
struct Type {
std::string name;
};
extern "C" int Func(Type);
}
包括.h:
#include <string>
#if defined __GNUC__
# pragma GCC system_header
#endif // __GNUC__
struct Type {
std::string name;
};
extern "C" int Func(Type);
main.cpp
#include "incl.h"
#include "x.h"
int main()
{
return 0;
}
G++ 发出警告,但已使用 # pragma GCC system_header
关闭。
那么,我怎样才能让 clang 在这样的环境中构建呢?
最佳答案
[dcl.link] At most one function with a particular name can have C language linkage. Two declarations for a function with C language linkage with the same function name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same function. ...
因此,::Func
和 XX::Func
必须引用相同的函数。但是您的两个声明具有不同的参数列表 - 一个采用 ::Type
参数,而另一个采用 XX::Type
参数。因此,它们不能是相同的函数,因此违反了引用的规则,并且程序格式不正确。曾经
修复程序的几种方法:
- 重命名
XX::Func
或::Func
,使它们成为单独的函数。确保每个都有一个定义。 - 在
incl.h
中,包含x.h
并将::Type
的定义替换为using XX::Type
。因此每个Type
都引用相同的类型,因此两个函数名称都引用相同的函数。确保只有一个定义。 - 在
x.h
中,包含incl.h
并将XX::Type
的定义替换为using ::Type
。达到与上面相同的效果。
顺便说一句,后者是一些标准库实现如何实现 <cstdlib>
及其 friend 的。它们包含相应的 C 标准库 header (在 <stdlib.h>
的情况下为 <cstdlib>
),该 header 声明了全局命名空间(C 中唯一的“命名空间”)中的所有内容,然后它们使用 std
将所有标准函数和类型选择到 using ::whatever
命名空间中。
附注不要使用 #pragma GCC system_header
(除非您正在编写系统 header )。它将抑制所有警告(由 #warning
指令生成的警告除外)。
关于c++ - 如何在不同命名空间中使用双重声明的 extern "C"函数进行 clang 构建(如 msvc 和 gcc),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55867172/