关于c c++ libraries互相linking的问题。
undefined reference
有几次在link libraries的时候会出现 undefined reference 的问题,明明已经把.so文件放到了命令后面,但还是有问题。除了网上找的到的常见原因,还有一个比较容易忽略的就是name mangling的问题。比如使用nm
命令进行查看,注意调用方和被调用方都需要查看一下。对于 nm
command,还可以使用-C
参数来查看没有name mangling时候的signature. Using the -D
parameter can only show the dynamic symbol. More informaion can be shown by man nm
operation.
-bash-4.2$ nm CMakeFiles/main.dir/main.cpp.o |
这个是main
生成的.o文件中的symbol
这个是目标library的symbol
-bash-4.2$ nm libfoo.so |
可以看到里面的symbol是不一样的,究其原因就是编译main文件的时候采用的是cpp的compiler(main.cpp文件),而编译libfoo的时候采用的是c的compiler(foo.c)。具体fix的手段一种是采用相同的compiler,比如都使用cpp的,或者是都使用c的。或者是按照stackoverflow这里的解释,采用extern C
的关键字来强制地按照c的方式进行编译。
具体使用CMake的时候,由于它会根据后缀自动选择,因此最好显示地指定compiler或者使用的语言。在一些完全用c写的library中,通常会加上如下的预编译命令来规避这个问题。
比如在.h 文件中进行如下定义
#ifdef __cplusplus |
这个例子说的内容比较详细,由于主要影响的是link阶段而不是compile阶段,因此在.h文件中加上相关的操作即可。
引用多个.h文件
本质上来说,这里的.h 相当于一个adaptor,cpp 文件本身会include这个.h 文件,调用方的.c文件在link相对应的cpp部分的时候(实际上具体执行link的是编译之后的.so文件),就会通过这个adaptor来找到对应的cpp部分。如果.h 文件中又include了多个其他的.h文件,这个时候其他的.h文件内也要使用extern c的操作。注意不要将include的声明放在extern的block中。
命名不规范引起的冲突
有一次遇到类似这个帖子中说的问题。
在完全使用c compiler的时候正常工作的code在使用了cpp的compiler的时候遇到了问题,这问题猛然一看不知到是什么原因,其实是很简单的事情。主要是因为一些old header file使用了macro来定义max min 这个就和cpp的使用max min 的方式产生了conflict,比如参数的个数这些。因为pure c 的code不带有namespace,也不会使用std::这样的方式,所以容易出现问题。即使是纯c的code,也要有一些前瞻性,这个code可能会被cpp调用,所以macro命名的时候也应该小心谨慎,加上一些特别的prefix。
reference
https://stackoverflow.com/questions/3789340/combining-c-and-c-how-does-ifdef-cplusplus-work