1

我的 C++ 库函数是int RFD_startBackgroundThread() 我的代码overlay.js

uri = addon.getResourceURI("components/mac/libReverbFirefoxExtensionLib.dylib");
this.extensionLib = ctypes.open(uri.path);
this.startBackgroundThread = this.extensionLib.declare("RFD_startBackgroundThread", ctypes.default_abi, ctypes.unsigned_int);

代码在最后一行引发异常。它说“ Couldn't find function symbol in library”。

该库是在 OS X Lion (10.7) 上结合了 i386 和 x86_64(但不是 PPC 架构)的“胖 dylib 二进制文件”。火狐版本 11。

迫切需要帮助。谢谢。拉胡尔。

4

2 回答 2

1

好吧,问题是,库没有按原样存储符号。要查看符号的实际名称,请使用转储库nm library-name(可选地将其重定向到 txt 文件,更易于阅读)。

我的例子中的符号写为__Z25RFD_startBackgroundThreadv。显然,我必须知道一个下划线并仅使用_Z25RFD_startBackgroundThreadv.

感谢迈克尔道特曼!

于 2012-07-11T23:21:53.490 回答
1

在包括 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 不能做什么以及原因的详细信息。

于 2012-07-11T23:36:57.643 回答