我已经看到了与C ++共享库的GCC链接,但我无法自己重现它。首先,我创建一个带有测试函数的C ++库:
g++ -shared -o libtest.so test.c
然后我有一个测试main函数,它调用库函数并像这样编译它
gcc -o prog.out main.c -L. -ltest
然后我收到错误
undefined reference to 'testfunc'
我认为是由库中的不同引用引起的... C命名函数testfunc和C ++命名函数[some stuff] __ testfunc [也许再一些东西]。
我也尝试过使用
gcc -o prog.out main.c -l:libtest.so
但这会导致同样的错误。
因此,我的问题是:如何将c ++库与gcc链接到c文件?
更新:我知道我可以使用extern "C"
,但这不是解决方法。也许链接器有一些参数呢?
Update2:只是认为第一部分可能只是用c ++编译并与gcc链接。还试过这个:
g++ -c testlib.c -o testlib.o
gcc -shared -o libtest.so testlib.o
gcc -o prog.out -l:libtest.so
仍然无效。旗帜有问题吗?
答案 0 :(得分:8)
是的,问题与共享库(我认为......)无关,而且与名称修改有关。
在标题中,您必须声明如下函数:
#ifdef __cplusplus
extern "C" {
#endif
void testfunc(void);
#ifdef __cplusplus
}
#endif
这将使testfunc
具有相同的符号和C和C ++的调用约定。
在我正在使用的系统上,C符号名称为_testfunc
,C ++符号名称(假设您不使用extern "C"
)将是__Z8testfuncv
,它编码有关参数类型的信息,因此重载将正常工作。例如,void testfunc(int x)
变为__Z8testfunci
,不会与__Z8testfuncv
发生冲突。
答案 1 :(得分:2)
使用g ++时,它会将 ALL 源编译为C ++。这意味着所有函数都使用C ++ ABI(这也包括名称修改)。当你使用gcc时,它使用C ABI编译* .c文件(没有名称修改)。
因此,使用两个不同的编译器编译相同的函数将生成不同的函数(在很多方面)。那是因为他们是不同的语言。强制g ++使用C ABI前缀编译一个函数extern "C"
extern "C" void testfunc(char*);
或者使用块版本
extern "C" {
<multiple Functions>
}
说实话,我再也没有用gcc编译任何东西了(除非有一些硬性要求这样做(在这种情况下我通常修复代码,所以它在C ++中工作))。如果使用g ++编译所有文件只会使进程更简单。
答案 2 :(得分:0)
如果你确定这不是因为名字错误。然后它意味着gcc无法找到库尝试提供库的完整路径,除非.so
文件位于标准位置。如果您不确定,请重新检查变量(函数)名称中的任何冲突。使用命名空间对类进行分组并定义类中的函数以避免命名冲突