【发布时间】:2011-05-17 19:28:39
【问题描述】:
我构建了一个名为 InterfaceLayer.so 的动态库。 当我打电话时:
> nm InterfaceLayer
作为输出,我得到一些看起来像这样的符号:
00000e28 T _Z5startv
虽然我期望它是“start”,就像我在代码中定义的函数的名称一样。
为什么会这样?
【问题讨论】:
我构建了一个名为 InterfaceLayer.so 的动态库。 当我打电话时:
> nm InterfaceLayer
作为输出,我得到一些看起来像这样的符号:
00000e28 T _Z5startv
虽然我期望它是“start”,就像我在代码中定义的函数的名称一样。
为什么会这样?
【问题讨论】:
这是因为 C++ 名称修改
nm -C
对它们进行解码。
为了防止名称混淆,
.
我的.h
extern "C"
{
void start();
void finish();
}
这将为它们提供“C”链接,这意味着它们不能被重载,不能通过引用传递,没有 c++ :)
【讨论】:
extern "C" 不代表函数不能通过引用传递。
听起来像C++ name mangling。
【讨论】:
c++filt _Z5startv
正如其他答案所提到的,这可能是因为 C++ 名称修改。如果您希望符号可以通过它的“未损坏”名称访问,并且它是在 C++ 中实现的,您需要向我们extern "C" 告诉 C++ 编译器它具有 C 链接。
在具有函数原型的标头中,您需要类似以下内容:
#if defined(__cplusplus)
extern "C" {
#endif
// the prototype for start()...
#if defined(__cplusplus)
}
#endif
这将确保如果函数被 C++ 编译器使用,它会在声明中获得 extern "C",并且如果它被 C 模块使用,它不会被 extern "C" 混淆说明符。
如果您在函数定义之前包含标头,则 .cpp 文件中的实现不需要这些东西。它将使用从先前声明中看到的链接规范。但是,我还是更喜欢用extern "C" 来装饰函数定义,以确保一切都同步(请注意,在 .cpp 文件中,您不需要 #ifdef 预处理内容 - 它总是被编译为 C++ .
【讨论】: