如何使用gcc链接C++共享库

4

我看到过一个使用GCC链接C++共享库的例子,但我自己无法复制它。因此,首先我创建了一个带有测试函数的C++库:

g++ -shared -o libtest.so test.c

然后我有一个测试主函数调用库函数,并像这样编译
gcc -o prog.out main.c -L. -ltest

然后我收到了错误提示。

undefined reference to 'testfunc'

我认为这是由于库中引用不同导致的... C命名函数为testfunc,而C++命名函数为[some stuff]__testfunc[maybe again some stuff]。

我还尝试使用

gcc -o prog.out main.c -l:libtest.so

但这导致了同样的错误。
因此,我的问题是:如何将c++库与gcc链接到c文件中?
更新:我知道可以使用extern "C",但这并不是解决的方式。也许有一些链接器参数可以代替?
更新2:刚才想到,第一部分可能只是用c++编译并链接到gcc上。也尝试过这种方法:
g++ -c testlib.c -o testlib.o
gcc -shared -o libtest.so testlib.o
gcc -o prog.out -l:libtest.so

仍然不起作用。标志有问题吗?


1
重复的问题:使用GCC/G++时C++库无法链接 - cyber_raj
2
你说的“那不是解决的方式”是什么意思?我告诉你,除非有你没有告诉我们的东西,否则那就是解决的方式。 - Dietrich Epp
@Dietrich Epp 看起来就像我在Update2中所写的那样完成了。而且我确定它不是用'extern'完成的 - 如果你想看一下这个项目:openjdk - marty bourque
3个回答

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冲突。


2
当你使用g++时,它会将所有源代码编译为C ++。这意味着所有函数都使用C ++ ABI(包括名称修饰)。当你使用gcc编译*.c文件时,它使用C ABI(没有名称修饰)。
因此,使用两个不同的编译器编译相同的函数将生成不同的函数(在很多方面)。这是因为它们是不同的语言
要强制g ++使用C ABI编译函数,请在其前面加上extern "C"
extern "C" void testfunc(char*);

或者使用块级版本

extern "C" {
<multiple Functions>
}

说实话,我已经不再使用gcc编译任何东西了(除非有一些强制要求这样做的情况(在这种情况下,我通常会修复代码,使其在C++中正常运行)。如果你用g++编译所有文件,那么整个过程会更加简单。


0

如果你确定这不是因为名字混淆的原因。那就意味着gcc找不到库,请尝试提供库的完整路径,除非.so文件位于标准位置。如果你不确定,重新检查变量(函数)名是否有冲突。使用命名空间将类分组,并在类内定义函数以避免命名冲突。


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