2016-04-26 72 views
12

我有一个超过10年的C库 - 我相信 - 在过去的美好时光里工作得很好,但是当我试图在C++源代码中使用它时(包含主函数)遇到了一些困难。如何使用C++将旧C代码与保留关键字相关联?

编辑:为了澄清,C库编译得很好,用gcc,它生成一个目标文件old_c_library.o。这个库应该以某种方式使用,以便您的main.c C源文件中的C头文件old_c_library.h#included。然后,您的主C源文件应该编译并通过与old_c_library.o链接在一起。在这里,我想使用C++源文件main.cpp来代替,并使用g++进行编译/链接。发生

以下三个问题,C++源文件的编译过程中:

  1. C库的头文件中的一个包含所述C++保留字new(它是一个整数的名称),导致致命错误;和
  2. C库的其中一个头文件包含calloc调用(缺少明确的类型转换),导致致命错误;和
  3. C库的各种文件包含代码,其中发生了带符号和无符号整数的比较,从而导致警告。

编辑:我试图使用#extern "C" { #include "obsolete_c_library.h" }“窍门”,正如评论中所建议的那样,但这并没有解决我的任何问题。

我可以通过重命名保留字的所有实例并将其替换为 - 基本上 - 其他任何内容来解决问题1。我可以通过调用calloc调用来解决问题2。我可能会尝试通过此处提出的建议来解决警告:How to disable GCC warnings for a few lines of code

但我仍然想知道,有没有办法以优雅,高级的方式克服这些困难,没有实际上触摸原始图书馆?


相关: Where is C not a subset of C++?Do I cast the result of malloc?How do I use extern to share variables between source files?

+1

在包含使用'new'作为变量名称的标题后,您可以在之前放置一个'#define new old',并在'#undef new'处输入 – user463035818

+3

如果关键字问题仅出现在旧库的实现中不是它的API),为什么不单独编译并且只将它链接到C++项目中? – nils

+2

唯一的优雅方式可能是更新库。一旦你被要求让代码腐烂,优雅就会消失,你将不得不使用任何肮脏的黑客来完成工作。 – ComicSansMS

回答

1

一般来说,如果这些头文件不是为了预期这种用法而构建的,那么将C头文件保存到C++源文件中并不安全。在某些情况下可以开始工作,但是您需要准备好修改头文件或为要访问的函数和全局变量编写自己的声明。

至少,如果C头文件声明了任何函数,并且您没有在C++中重新编译这些函数,那么您必须确保声明在您的C++代码中被分配了C连接。它的情况并不少见C头文件通过条件编译指令自动考虑这一点,但如果他们不这样做,那么你可以通过在C链接块包裹包含(S)做它的另一面:

extern "C" { 
#include "myclib.h" 
} 

如果C头文件中声明的全局变量的名字冲突C++的关键字,,哪些是你不需要引用,那么你可能能够使用预处理器重新定义它们:

#define new extern_new 
#include "myclib.h" 
#undef new 

这并不能保证工作,但值得一试。如图所示,在包含C头后,请不要忘记#undef这样的宏。

可能还有其他一些有趣的技巧可以用宏来调整特定的头文件到C++中,但是在某些时候,只需复制/重写所需的声明(并且仅限于那些)或者在你自己的C++头文件中。请注意,这样做并不会取消声明C链接的需要 - 该要求来自于由C编译器而不是C++编译器编译的库。

2
  1. 您可以写一个c头的副本,唯一的区别是缺少声明extern int new。然后使用新创建的C++友好标题而不是旧的不兼容标题。

    如果你需要从C++引用该变量,那么你需要做一些更复杂的事情。您将需要在c中编写一个新的包装库,该文件公开了 读写函数 指向C++的指针,该指针可用于访问不幸命名的变量。

    如果某些内联函数引用了变量,那么您可以将它们从重复头文件中删除,如果需要从C++调用它们,请以C++友好方式重新实现它们。只要不要在extern "C"内重新实现相同的名称,因为这会使您与原有的内联函数发生冲突,这些内联函数可能由一些现有的c代码使用。

  2. 做与1中所述相同的头重复,省去有问题的内联函数并在需要时重新实现。

  3. 如您所知,可以忽略或禁用警告。无需修改原始标题。您可以用不会产生警告的版本重写任何{const,type} - 不安全的内联函数,但是您必须考虑您的时间是否值得。

这种方法的缺点是你现在有一些/所有标题的两个vesions。 C++使用的新的和旧的代码可能使用的旧的。


如果你可以放弃不触及原有库的要求,不需要与现有编译的二进制工作,然后一个优雅的解决办法是简单地重命名有问题的变量(1)。使非C++兼容的内联函数(2.)非内联并将它们移动到c源文件中。修复生成警告的不安全代码(3.),或者如果警告是特定于C++的,则只需使函数非内联。

+0

好的,我回想起这是一个“连接”问题,正如很多评论指出的那样。消化所有这些可能需要一些时间。正如我所想的,如果可能,最优雅的方式是更新生锈的库。 – Matsmath