“在库中找不到函数符号” - JS-Ctypes [英] "Couldn't find function symbol in library" - JS-Ctypes

查看:219
本文介绍了“在库中找不到函数符号” - JS-Ctypes的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的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);

代码在最后一行引发异常。它说在库中找不到函数符号



库是一个fat dylib二进制文件在OS X Lion(10.7)上结合了i386和x86_64(但不包括PPC拱门)。 Firefox版本11。



非常需要帮助。
谢谢。
Rahul。

解决方案

在大多数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知道关闭_,但它不知道如何打乱你的功能,因为你只是给它一个名字,而不是一个完整的原型。所以,你必须找出其他方式,你的函数mangled的名称是 _Z25RFD_startBackgroundThreadv



没有可移植的标准如何名称被打乱。但是,Apple使用的C ++ ABI基于 Itanium C ++ API < a>,这需要一个API来修改和去除C ++函数。 Xcode附带了一个名为c ++ filt的工具,它封装了在命令行中使用的API,但是它只能处理解除绑定,而不是绑定。所以,它可以告诉你: _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}'

...将打印所有符号的demangled名称。



但是最好的办法是创建一个很小的.cpp文件,一个原型,编译它,然后用otool -SV tiny.a来查看这个名字。

你可以调用C ++函数。

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


My C++ Library function is int RFD_startBackgroundThread() My code in the overlay.js is

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);

The code throws an exception on the last line. It says "Couldn't find function symbol in library".

The library is a "fat dylib binary" combining both i386 and x86_64 (but not PPC arch) on OS X Lion (10.7). Firefox version 11.

Desperately need help. Thanks. Rahul.

解决方案

In most Unix platforms, including OS X, C functions are mapped to symbols just by prefixing with an underscore, so int foo(int) ends up as just _foo.

But that doesn't work for C++, because in C++, you can have two different functions with the same name, in a variety of different ways—you can have int foo(int) and double foo(double), or int MyClass::foo(int), or int foo<int>(int), and so on. So, C++ functions have to be "mangled" to give a unique string. (And then, that unique string is treated like a C function—that is, prefixed with an "_".)

jsctypes knows about knocking off the _, but it can't know how to mangle your function, because you're just giving it a name, not a full prototype. So, you have to figure out in some other way that the mangled name of your function is _Z25RFD_startBackgroundThreadv.

There's no portable standard for how names get mangled. However, the C++ ABI that Apple uses is based on the Itanium C++ API, which requires an API to mangle and demangle C++ functions. Xcode comes with a tool called c++filt that wraps up that API for use at the command line—but it only handles demangling, not mangling. So, it can tell you that _Z25RFD_startBackgroundThreadv means RFD_startBackgroundThread(), but it can't get the other way around.

One way to get the mangled name is to start with nm libfoo.dylib, then use c++filt to check the ones that look like good candidates, until you find one that matches the prototype you're looking for.

Another way is to automate that. Something like this:

nm libfoo.dylib | awk 'NF==2 {printf "%s ",$1; system("c++filt " $2)} NF!=2{print $0}'

… will print the demangled names of all of your symbols.

But probably the best way to go about it is to create a tiny .cpp file that has nothing in it but that one prototype, compile it, and use "otool -SV tiny.a" to see the mangled name.

So, it's not that hard to get the name of the symbol for the C++ function you want to call.

But that doesn't mean you can just call it as if it were a C function. For one pretty obvious example, if you want to call (non-static) Foo::bar(int), you'd better have a valid thing to pass as a "this" pointer, and know how to pass it. See https://bugzilla.mozilla.org/show_bug.cgi?id=505907 for details on what jsctypes in Mozilla can't do, and why.

这篇关于“在库中找不到函数符号” - JS-Ctypes的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆