1

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

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 arch ではない) の両方を組み合わせた「ファット dylib バイナリ」です。Firefox バージョン 11。

どうしても助けが必要です。ありがとう。ラフル。

4

2 に答える 2

1

OS X を含むほとんどの Unix プラットフォームでは、C 関数はアンダースコアを前に付けるだけでシンボルにマップされるため、最終的にint foo(int)_foo.

しかし、これは C++ では機能しません。C++ では、同じ名前の 2 つの異なる関数をさまざまな方法で使用できるためです。 int foo(int)and double foo(double)、 or int MyClass::foo(int)、またはなどを使用できますint foo<int>(int)。そのため、一意の文字列を与えるには、C++ 関数を「マングル」する必要があります。(そして、その一意の文字列は C 関数のように扱われます。つまり、"_" のプレフィックスが付けられます。)

jsctypes は _ をノックオフすることを知っていますが、完全なプロトタイプではなく名前を付けているだけなので、関数を壊す方法を知ることはできません。したがって、関数のマングル名が であることを別の方法で把握する必要があります_Z25RFD_startBackgroundThreadv

名前がマングルされる方法についての移植可能な標準はありません。ただし、Apple が使用する C++ ABI はItanium C++ APIに基づいており、C++ 関数をマングルおよびデマングルするための API が必要です。Xcode には、コマンド ラインで使用するためにその API をラップする c++filt というツールが付属していますが、これはマングリングではなく、デマングリングのみを処理します。つまり、それが_Z25RFD_startBackgroundThreadv意味することはわかりますがRFD_startBackgroundThread()、その逆はできません。

マングルされた名前を取得する 1 つの方法は、 から始めてnm libfoo.dylib、探しているプロトタイプに一致する名前が見つかるまで、適切な候補と思われる名前を c++filt を使用してチェックすることです。

別の方法は、それを自動化することです。このようなもの:

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

… すべてのシンボルのデマングリングされた名前を出力します。

しかし、おそらく最善の方法は、1 つのプロトタイプだけを含む小さな .cpp ファイルを作成し、それをコンパイルして、「otool -SV tiny.a」を使用してマングルされた名前を確認することです。

したがって、呼び出したい C++ 関数のシンボルの名前を取得するのはそれほど難しくありません。

しかし、それは、C 関数であるかのように呼び出すことができるという意味ではありません。非常に明白な例として、(非静的) Foo::bar(int) を呼び出したい場合は、「this」ポインターとして渡す有効なものがあり、その渡し方を知っている必要があります。Mozilla の jsctypes で実行できないこととその理由の詳細については、https : //bugzilla.mozilla.org/show_bug.cgi?id=505907 を参照してください。

于 2012-07-11T23:36:57.643 に答える
1

問題は、ライブラリがシンボルをそのまま保存しないことです。シンボルの実際の名前を確認するには、次を使用してライブラリをダンプしますnm library-name(オプションで、読みやすい txt ファイルにリダイレクトします)。

私の場合の記号は と書かれていまし__Z25RFD_startBackgroundThreadvた。どうやら、私は 1 つのアンダースコアを知り、 のみを使用する必要があり_Z25RFD_startBackgroundThreadvました。

マイケル・ドーターマンに感謝!

于 2012-07-11T23:21:53.490 に答える