0

私は MinGW (Cygwin ではない) を使用しており、Windows で実行するために Mac に正常に移植した OSS コードを取得しようとしています。望ましい最終ビルドは、JNI ライブラリとして使用できる .DLL (これは Mac では .jnilib です) ですが、インターフェイスをラップする最後の .cpp ファイルのコンパイルに問題があります。

問題は、.cpp ファイル内のすべての関数がコンパイル時に次の形式でエラーを生成することです。

g++ -I/various/such/entries -D_inline=__inline -I/c/java/include -I/c/java/include/win32 -c -o com_me_package_ClassName.o com_me_package_ClassName.cpp
com_me_package_ClassName.cpp:84:31: error: external linkage required for symbol 'void Java_com_me_package_ClassName_Moo(JNIEnv*, jclass)' because of 'dllexport' attribute
// ditto the above for every such function

上記のエラーが表示されている 1 つの関数を見てみましょう。

#include <jni.h> // of course this is in here
static JNIEXPORT void JNICALL Java_com_me_package_ClassName_Moo
    (JNIEnv *env, jclass clazz) {
printf("Moo!\n");
}

これをグーグルで調べた後、他の誰かが「静的」関数が問題であるプロジェクトを持っているのを見たので、エラーを作成した関数の前に.cppファイルに次のハックを追加しようとしました:

#ifdef WIN32
#define static 
#endif

ただし、これでコンパイルの問題は解決しましたが、リンクの問題が発生しただけでした。これは、ifdef 手段の結果である場合とそうでない場合があります (マングリングのみに関係している可能性があります)。次に示すように、FOO_int2str などの -L 指定された静的ライブラリから Mac ビルドで確実に検出されたにもかかわらず、欠落しています。

g++ -D_inline=__inline -shared -o /output/lib/libfoo_jni.dll   com_me_package_ClassName.o -L/some/number/of/such/things -lz -lzipfile
com_me_package_ClassName.o:com_me_package_ClassName.cpp:(.text+0x84) : undefined reference to `_imp__FOO_int2str'

私は少し途方に暮れています。私が Google で見つけた数少ないもののほとんどは、他のビルド環境 (たとえば、cygwin や Microsoft が提供するコンパイラー) とかなり強い文脈上の結びつきがあります。私は gcc と MinGW を使用していますが、dlltool や Cygwin などに関連する回答は避けたいと考えています。これは、私が作業しているコードが多くの手を通過しており、ケージに入れられた稲妻のような闇の魔法 (音声認識など) が含まれているためです。 .. 変更すればするほど、Mac プラットフォームの既存の機能が失われるリスクが高くなります。

私はメイクファイルを書く初心者です。私が現時点でこの建物を持っているのは幸運な偶然です。コードは、デスクトップ プラットフォームではなくモバイルをターゲットとする非常に重いビルド ゲシュタルトを含むギガバイト規模のコーパスから抽出されたものだからです。ダンプする必要があることを知っていたビルド コンテキストと、それを正常に実行できた (少なくとも Mac の場合)。そこに戻ることはありません !

これらの関数をコンパイルおよびリンクする g++ (または gcc のような同等のもの) への明示的なコマンドライン呼び出しに関するアドバイスを事前に感謝します。

調子

4

1 に答える 1

2

static内部リンケージが得られるため、関数を作成したくありません。エラー メッセージが示すように、これはエクスポートされる関数と互換性がありません。JNI 関数には外部リンケージが必要です。staticに置き換えることで実現できますextern。ただし、外部リンケージは関数のデフォルトであるため、単にstaticリンケージ指定子を削除して省略できexternます。

C ではなく C++ としてコンパイルするため、C リンケージも指定する必要がありますextern "C"。デフォルトの C++ リンケージを使用すると、リンカ エラーの原因であると思われる C++ 名マングリングが発生します。

したがって、コードは次のようになります。

#include <jni.h> 

extern "C"
{

JNIEXPORT void JNICALL Java_com_me_package_ClassName_Moo
    (JNIEnv *env, jclass clazz) 
{
    printf("Moo!\n");
}

}
于 2012-05-21T18:37:47.460 に答える