如何删除共享库中符号周围的周围字符?

时间:2016-12-21 16:20:43

标签: linux gcc g++ shared-libraries name-mangling

我使用g++编译了一个库,我希望用gcc链接它 问题是我在链接时遇到错误:

  

未定义引用' functionName`

(functionName是库中的函数名称)

虽然函数存在于符号列表中,但我在链接时指定了gcc的路径。

之所以会发生这种情况是因为该功能会出现在带有周围字符的列表中(我认为这是为了覆盖?):

Z12functionNameiSt9__va_list

我知道要删除这些字符,我应该用extern "C"包围函数声明。我这样做了:

//header.hpp
extern "C" int functionName(int argc, ...);

但是周围的字符仍然出现在符号列表中的函数名称周围。这就是gcc无法找到它的原因。

我在Ubuntu桌面16上与arm-poky-linux-gnueabi-gccarm-poky-linux-gnueabi-g++交叉编译linux arm yokto。

为什么不删除周围的字符以及如何删除它们?我永远不会覆盖这个功能,所以如果这些功能真的用于覆盖那么我就不需要它们了。

修改

解决。声明中的函数签名与其定义中的签名不同......因此extern关键字一无所获。

int functionName(int argc, ...); //declaration
int functionName(int argc, va_list args) //definition

2 个答案:

答案 0 :(得分:1)

这些字符是名称错误。它们对函数签名进行编码,因此C ++重载可以正常工作(例如。int foo(int)int foo(float)是不同的符号)。

如果您的API是C,则需要修复库以避免损坏。将其构建为C或在其代码中添加extern "C"。如果您的API是C ++,请从标题中删除extern "C"

如果受损的名称不匹配(不同的修改),那么您可能会遇到ABI兼容性问题。在这种情况下,尝试修复链接问题是错误的解决方案。您需要确保使用与库相同的ABI构建代码。

c++filt工具应该能够将损坏的符号解码为签名。这可以用来弄清楚差异是什么。

鉴于您使用g++构建了库并尝试与gcc建立链接,您可能需要C API并使用extern "C"重建库是你需要的。

答案 1 :(得分:0)

“周围的人物”实际上是name mangling。所以更好地谈论受损的名字

您可能应该添加

#ifdef __cplusplus
extern "C" {
#endif

靠近(公共)头文件的开头(你最好在C和C ++的公共子集中编码),以及匹配的

#ifdef __cplusplus
}; // end of extern "C"
#endif

接近尾声。另请参阅this

您应该将所有公共标题(以及可能包含的标准C标题)包含在内(不仅仅是单个函数)。

您可以使用gcc -H进行编译,以列出所包含的标题,或g++ -C -E以获取预处理的表单(并进行检查)。