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 を参照してください。