如何将旧C代码与C++中的保留关键字链接起来?

Mat*_*ath 12 c c++ portability suppress-warnings

我有一个10岁以上的C库 - 我相信 - 曾经在过去的好日子里工作得很好,但是当我尝试将它与C++源码(包含主要功能)一起使用时,有一天我遇到了有些困难.

编辑:澄清一下,C库编译得很好gcc,它会生成一个目标文件old_c_library.o.该库认为在某种程度上,这样的C头文件中使用的old_c_library.h#include在D main.cC源文件.然后你的主要C源文件应该编译并与old_c_library.ovia 链接在一起gcc.在这里,我想使用C++源文件main.cpp,并编译/链接它g++.

在编译C++源文件期间发生了以下三个问题:

  1. C库的一个头文件包含C++保留字new(它是一个整数的名称),导致致命错误; 和
  2. C库的一个头文件包含一个calloc调用(缺少显式类型转换),导致致命错误; 和
  3. C库的各种文件包含发生有符号和无符号整数比较的代码,这会导致警告.

编辑:我试图使用#extern "C" { #include "obsolete_c_library.h" }"技巧",如评论中所建议,但这并没有解决我的任何问题.

我可以通过重命名保留字的所有实例并用 - 基本上 - 替换它们来解决问题1.我可以通过类型化calloc调用来解决问题2 .我可能会尝试通过这里建议的想法来解决警告:如何禁用几行代码的GCC警告.

但我仍然想知道,有没有办法以优雅,高层次的方式克服这些困难,而不是真正触及原始图书馆?


相关: C在哪里不是C++的子集?并且不要我投malloc的结果?以及如何使用extern在源文件之间共享变量?.

Joh*_*ger 3

一般来说,#include如果 C 头文件不是按照预期使用而构建的,那么将 C 头文件放入 C++ 源代码中是不安全的。在某些情况下,它可以工作,但您需要准备好修改标头或为要访问的函数和全局变量编写自己的声明。

至少,如果 C 头文件声明了任何函数,并且您没有在 C++ 中重新编译这些函数,那么您必须确保在 C++ 代码中为这些声明分配了 C 链接。C 标头通过条件编译指令自动解决这一问题的情况并不罕见,但如果它们没有这样做,那么您可以通过将包含内容包装在 C 链接块中来在另一侧完成此操作:

extern "C" {
#include "myclib.h"
}
Run Code Online (Sandbox Code Playgroud)

如果 C 标头声明的全局变量的名称与 C++ 关键字冲突,并且您不需要引用该全局变量,那么您可以使用预处理器重新定义它们:

#define new extern_new
#include "myclib.h"
#undef  new
Run Code Online (Sandbox Code Playgroud)

这不能保证有效,但值得一试。#undef在包含 C 标头后不要忘记此类宏,如图所示。

您可能还可以使用宏来使用其他有趣的技巧来使特定标头适应 C++,但在某些时候,仅在您的主 C++ 源代码或您自己的源代码中复制/重写所需的声明(并且仅复制/重写这些声明)更有意义C++ 标头。请注意,这样做并不能消除声明 C 链接的需要——该要求来自于由 C 编译器而不是 C++ 编译器编译的库。