“无法在库中找到函数符号” - JS-Ctypes

时间:2012-07-11 22:31:59

标签: macos firefox firefox-addon osx-lion jsctypes

我的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”。

该库是一个“胖dylib二进制”,在OS X Lion(10.7)上结合了i386和x86_64(但不是PPC arch)。 Firefox版本11。

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

2 个答案:

答案 0 :(得分:1)

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

我案例中的符号写成__Z25RFD_startBackgroundThreadv。显然,我必须知道一个下划线,只使用_Z25RFD_startBackgroundThreadv

感谢Michael Dautermann!

答案 1 :(得分:1)

在大多数Unix平台中,包括OS X,C函数只是通过在下划线前加上映射到符号,因此int foo(int)最终只是_foo

但是这对C ++不起作用,因为在C ++中,你可以用各种不同的方式拥有两个不同的同名函数 - 你可以拥有int foo(int)double foo(double),或者int MyClass::foo(int)int foo<int>(int),依此类推。因此,C ++函数必须是“mangled”才能给出唯一的字符串。 (然后,该唯一字符串被视为C函数 - 前缀为“_”。)

jsctypes知道如何敲掉_,但它不知道如何破坏你的功能,因为你只是给它一个名字,而不是一个完整的原型。因此,您必须以其他方式弄清楚函数的错位名称为_Z25RFD_startBackgroundThreadv

没有关于名称被破坏的便携式标准。但是,Apple使用的C ++ ABI基于Itanium C++ API,它需要一个API来破坏和解码C ++函数。 Xcode附带了一个名为c ++ filt的工具,它包装了该API以供命令行使用 - 但它只处理demangling,而不是修改。因此,它可以告诉您_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”来查看被破坏的名称。 / p>

因此,获取要调用的C ++函数的符号名称并不难。

但这并不意味着你可以把它称为C函数。对于一个非常明显的例子,如果你想调用(非静态)Foo :: bar(int),你最好有一个有效的东西作为“this”指针传递,并知道如何传递它。有关Mozilla中不能执行哪些jsctype以及原因的详细信息,请参阅https://bugzilla.mozilla.org/show_bug.cgi?id=505907