在包括 OS X 在内的大多数 Unix 平台中,C 函数仅通过以下划线作为前缀映射到符号,因此int foo(int)
以_foo
.
但这不适用于 C++,因为在 C++ 中,您可以以各种不同的方式拥有两个具有相同名称的不同函数——您可以拥有int foo(int)
and double foo(double)
、 or int MyClass::foo(int)
、 orint foo<int>(int)
等等。因此,C++ 函数必须“错位”才能给出唯一的字符串。(然后,该唯一字符串被视为 C 函数,即以“_”为前缀。)
jsctypes 知道敲掉 _,但它不知道如何破坏你的函数,因为你只是给它一个名字,而不是一个完整的原型。因此,您必须以其他方式找出函数的错误名称是_Z25RFD_startBackgroundThreadv
.
对于名称如何被破坏,没有可移植的标准。然而,Apple 使用的 C++ ABI 是基于Itanium C++ API的,它需要一个 API 来破坏和解散 C++ 函数。Xcode 附带了一个名为 c++filt 的工具,它封装了该 API 以供在命令行中使用——但它只处理 demangling,而不是 mangling。所以,它可以告诉你这_Z25RFD_startBackgroundThreadv
意味着RFD_startBackgroundThread()
,但它不能反过来。
获得重整名称的一种方法是从 开始nm libfoo.dylib
,然后使用 c++filt 检查那些看起来像好的候选者,直到找到与您正在寻找的原型匹配的那个。
另一种方法是自动化。像这样的东西:
nm libfoo.dylib | awk 'NF==2 {printf "%s ",$1; system("c++filt " $2)} NF!=2{print $0}'
... 将打印所有符号的解构名称。
但可能最好的方法是创建一个小的 .cpp 文件,其中除了一个原型之外什么都没有,编译它,然后使用“otool -SV tiny.a”查看损坏的名称。
因此,获取要调用的 C++ 函数的符号名称并不难。
但这并不意味着您可以像调用 C 函数一样调用它。举一个非常明显的例子,如果你想调用(非静态)Foo::bar(int),你最好有一个有效的东西作为“this”指针传递,并且知道如何传递它。请参阅https://bugzilla.mozilla.org/show_bug.cgi?id=505907了解有关 Mozilla 中的 jsctypes 不能做什么以及原因的详细信息。