AndroidアプリでjavaからC++のコードを呼び出すためのJNIというインターフェースを使う方法を共有します。
私自身たくさんググって5時間ぐらいかかったので、簡単にまとめます。
本記事のテーマ
私の使用したPCはUbuntu18.04です
Native C++プロジェクトの作成
File > New > New Project > Native C++を選択すしてプロジェクトを作成する。
※Native C++は一番下にあるのでご注意ください
(筆者は下にあることを知らず、探すのに時間がかかりました 笑)
デフォルトでapp/src/main/cpp/native-lib.cppがありますので、プロジェクト作成後、エミュレータで実行してください。「Hello from C++」と表示されると思います。
C++ソースファイルの追加
app/src/main/cppディレクトリを右クリックして
New > C/C++ Sorce File から追加してください。
ヘッダファイルを追加したい場合はCreate an associated headerのチェックボックスをチェックしてください。
例:「testJNI.cpp」を追加
JavaとC++ファイルのリンク
MainActivity.java
・C++ライブラリをロードします。
System.loadLibrary("testJNI");
・C++の関数を呼び出します。
tv.setText(String.valueOf(stringFromJNI2("aiueo")));
・nativeコード(C++)の関数をjavaで使えるように宣言します。引数を与えてC++に渡すこともできます。
public native int stringFromJNI2(String str);
package com.example.anative;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
System.loadLibrary("testJNI");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
tv.setText(String.valueOf(stringFromJNI2("aiueo")));
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
public native int stringFromJNI2(String str);
}
testJNI.cpp
cppではjavaとリンクさせるために関数名に規則があります。
・java_ + ソースディレクトリからの相対パス + 関数名
・ソースディレクトリからの相対パスはjavaファイルの1行目にあるpackage名を使用すると良い。
package com.example.anative;
・javaとc/c++で方を共有するために、jstringやjint、jobjectなどの方を用います。
・JNIEnv* は VM へのポインタで、jobject は Java サイドから渡される暗黙的な this オブジェクトへのポインタです。
例:今回は引数はstringで受けとり、変数はintで返します。
#include
#include
extern "C" JNIEXPORT jint JNICALL
Java_com_example_anative_MainActivity_stringFromJNI2(
JNIEnv *env,
jobject /* this */,
jstring str){
std::string hello = "Hello from testJNI";
int a;
a = 3;
return a;
}
CMakeList.txt
・add_libraryでリンカ設定を追加します。
・target_link_librariesで出力先を設定
一番下に追加すれば良いです。
リンカの設定ですが、SHARED以外にSTATICというのもあるらしく、参考サイト「C++ でのライブラリ作成と再利用」を参考文献に載せますのでご覧ください。
add_library(testJNI SHARED testJNI.cpp)
#find_library( log-lib log)
target_link_libraries( native-lib testJNI ${log-lib})
以上を実行していただければアプリ上に"3"と表示されるなんの意味もないアプリが動きます。
これを使ってjavaとc++を使用したアプリを作成してください!
参考文献