编译包含extern "C"的程序

10

我正在尝试使用makefile编译其他人已经编写好的程序,使用cygwin。我收到了很多错误消息,其中许多都抱怨error: template with C linkage

经过搜索,似乎问题与extern "C"有关。这行代码包含在文件cygwin/usr/include/pthread.h中,并在一个头文件中使用#include < pthread.h >包含。当我删除该行时,大多数错误消息都消失了。但还有一些错误消息保留了下来,如下所示:

/usr/include/pthread.h:67:5: error: previous declaration of ‘int pthread_atfork(void (*  )(),void ( *)(), void ( *)())’ with ‘C++’ linkage

/usr/include/sys/unistd.h:136:5: error: conflicts with new declaration with ‘C’ linkage

有人知道如何修复这个问题吗?我很想坐下来详细学习所有这些东西,但在需要运行这个程序之前我没有时间了...


1
如果没有看到您正在尝试编译的实际代码,我们无法提供太多帮助。 - Jim Lewis
7
不要修改pthread.h,那很可能是正确的,你需要找出为什么会出现原始错误,这个错误很可能并不存在。我首先会查找的候选项是宏。 - David Rodríguez - dribeas
3个回答

12

编辑:根据评论中的交流,罪犯是构建目录中的头文件(Endian.h),它与系统包含文件 /usr/include/endian.h 冲突。它被包含在系统头文件之前,导致构建问题。这些文件发生冲突是因为在 Windows 上大小写不敏感。根本原因是最初答案中建议的原因。extern C 结构无意中泄漏到了定义模板时会引起错误的 C++ 代码中。

我会检查您的头文件中是否存在“悬挂”的 C 链接结构。这将在您编写的代码中出现(而不是任何系统头文件;那些可能是安全的)。

头文件中的代码包含在以下代码块中:

顶部:

#ifdef __cplusplus
extern "C" {
#endif

最后,在底部:

#ifdef __cplusplus
}
#endif
如果底部缺失,则顶部的影响会无意中延伸到其他头文件中的代码。这会导致像你遇到的问题一样的问题。

@JonP.Harris 奇怪的是,正如我所提到的,我没有亲自编写这段代码,我确信它适用于其他人。我已经查找了你在头文件中提到的代码,但到目前为止还没有找到。不过我怀疑作者们使用的是Linux,而我使用的是Windows,在Google上搜索发现在Windows上可能存在pthread和Cygwin的一些问题? - jorgen
1
@jorgen 你可以查看预处理输出。按原样运行编译器命令,但将“-c”选项替换为“-E”。输出应该进入使用“-o”选项指定的文件中。查看它,如果你喜欢,可以将文件粘贴到某个地方并在此处发布链接(如果需要帮助)。 - Ziffusion
你可以直接从构建输出中复制并粘贴命令到 shell 中执行。该命令应该是一个 gcc 调用,应该在错误消息之前。只要你在正确的目录中,它就应该能够正常工作。 - Ziffusion
1
你正在编译的目录中似乎有一个名为endian.h的文件。它正在干扰你的构建。编译器正在包含该文件,而不是来自/usr/include的标准文件。 - Ziffusion
1
啊,大小写的问题是为什么它对其他人有效而对你无效的原因。在Windows上,大小写不敏感。我可以编辑答案以反映这个交流。然后你就可以接受它了。 - Ziffusion
显示剩余4条评论

10

当编译器编译C和C++代码的混合时,这个问题就会出现。extern "C"语法是一种告诉C++编译器需要让C编译器也能够访问该函数的方式。C编译器不理解extern的用法,所以通常你可以这样隐藏它:



    #ifdef __cplusplus
    extern "C" {
    #endif<br>
    void whatever();<br>
    #ifdef __cplusplus
    }
    #endif

不过,您不应该更改系统头文件,因为这些文件出错的概率非常小。更有可能是您自己的头文件缺少上面的闭合括号。


3
与被接受答案相似,对我来说这也是一个嵌套问题,但并非涉及“#ifdef/#endif”,因此我在这里作为参考添加。

在我的情况下,这个错误是由嵌套的extern "C"结构引起的。一个包含extern "C"结构的头文件被包含在另一个extern "C"结构内部,导致编译器/预处理器混淆。

文件a.h:

#ifdef __cplusplus
extern "C"{
#endif

#include "b.h"

#ifdef __cplusplus
}
#endif

文件 b.h

#ifdef __cplusplus
extern "C"{
#endif

void someFunctionDeclaration();

#ifdef __cplusplus
}
#endif

#include "b.h"移到a.hextern "C"结构之外可以解决问题。

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