質問: Android NDKを使ったライブラリのコードを読んでいたところ、 ``` JNIEXPORT jlong JNICALL Java_org_gearvrf_NativeShaderManager_ctor(JNIEnv * env, jobject obj); ``` のようにJNIメソッドの前に`JNIEXPORT 戻り値の型 JNICALL`のように宣言してある箇所が多数ありました。 単に`戻り値`だけにしても動作は変わらないようなのですが、この`JNIEXPORT`と`JNICALL`の意味は何なのでしょう?
回答: JNIEXPORTは、共有ライブラリ(*.so)が作られる際、その関数を外部に公開するという宣言のようなものです。逆にこれがなければ、Javaから呼ばれる関数ではないということになります。あと、ソースがC++で書かれている場合は、特別な指示が無いと、関数の名前がC++の型情報を含む特有な関数名に変更(マングル、マングリング)されてしまいます。それを避け、C言語の関数として公開(エクスポート)するために、JNIEXPORTに extern "C" の様な指令が含まれている場合があります。 JNICALLは、Javaの仮想マシンがC言語の関数を呼び出す際、どのような方法(関数の呼び出しルール)を採用すべきかが定義されます。引数をスタックで渡すかレジスタで渡すかといったルールを、Java側とC側で合意しておくための指示で、、Wikipedia等で「呼出規約」「ABI (Application Binary Interface)」を調べていただけるとわかるかと思います。 もし、JNIEXPORTやJNICALLを省略しても正常に動作したとすると、たまたま運が良かったということです。CPUやOSが違っても、同じソースのままでも、JNIEXPORTやJNICALLが、動作環境の差異を吸収してくれます。