NDKを使うとAndroid開発でこんなことできます。
- ネイティブコードを呼び出す
- コードをC/C++で書くことができる
ただその手順がメチャクチャ面倒でした。
同じように困っている人に向けて、
Android開発で NDKからC/C++を使う手順 をまとめます。
最低限の手順だけまとめると次の通り。
※ ただし Android Studio での手順。
このページの目次
1.C/C++ ファイルを既存プロジェクトに追加
まずプロジェクトペインから【Project】を選択
その中から 【app】=>【src】と開き、【main】を右クリックして 【New】=>【Directory】を選択。出てきたダイアログに "cpp" と入力して作成。(あるいは "jni" という名前でも良いらしい)
作成したcppディレクトリ上で右クリックし、【New】=>【C/C++ source file】 を選択。ダイアログから 適当にC/C++ソースファイル名を入力。
ここでは hello.cpp を作りました。
もちろんC++ではなくCでもOKです。
ビルドには CMakeLists.txt も必要です。
その作り方は プロジェクトペインのルートディレクトリで右クリックし、【New】=>【File】を選択。ダイアログから "CMakeLists.txt" を入力して作成
これで下準備の下準備が完了。
2.CMakeLists.txtにビルド設定を追加
CMakeLists.txtはC/C++のビルド設定ファイル
ここでは次のような設定を書いてみました。
▼ CMakeLists.txtの設定例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
cmake_minimum_required(VERSION 3.4.1) add_library( # 識別用ライブラリ名を指定 hello # 共有ライブラリとしてビルドさせる SHARED # C/C++ソースへの相対パス指定 src/main/cpp/hello.cpp ) target_link_libraries( hello android log ) |
大事なポイントは次の2つ
- add_library
ここには作成したC/C++ライブラリの名前・ビルド方法・相対パス指定する。ここでは hello.cpp の設定を追加(内容については後述)
- target_link_libraries
ここには独自ライブラリ名、android, log を指定しておく。こうすることでC/C++側でもログ出力が使えるように
この2点さえ押さえとけばOK
3.モジュール側(アプリ側)のbuild.gradleを編集
次にモジュール側の build.gradle を開きます。
編集画面が開いたら、以下の内容を追加
1 2 3 4 5 6 7 8 9 10 11 |
android { compileSdkVersion 29 // 中略... externalNativeBuild { cmake{ path "CMakeLists.txt" } } } |
CMakeLists.txt のパスを指定するだけです。
これでネイティブメソッドを呼び出す準備は完了
4.C/C++ソースでネイティブメソッドを定義
ここでは次のネイティブメソッドを定義しました。
- 関数名は getMessage という名前
- 引数として文字列を1つ受け取る
- その引数を含むメッセージを返す
やってることは単純明快です。
そのために書いたC++コードがこちら
▼ ネイティブメソッドのC++コード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <string.h> #include <string> #include <jni.h> extern "C" JNIEXPORT jstring JNICALL Java_com_example_example_MainActivity_getMessage( JNIEnv* env, jobject thiz, jstring j_name ){ const char* name = env->GetStringUTFChars(j_name, 0); std::string msg = "Hello "; msg += name; msg += " from JNI!!"; return env->NewStringUTF(msg.c_str()); } |
ここで大事なのは次の3点
- マングリングを無効化
上コードのように extern "C" としてマングリング(C++特有の機能)をさせなくする。C++の場合、こうしないとビルドエラーが出る
- メソッドの命名規則
例えば com.example.example のMainActivityから呼ばれる場合、 Java_com_example_example_MainActivity_getMessage という名前にする。Java側からは getMessage("hoge"); で呼び出せる。
- JavaとC++でのデータ交換
例えばJavaでは文字列に String を使うが、C/C++では jstring が代替として使える。ネイティブ側からJavaに返すときは env->NewStringUTF(msg.c_str()); のように変換する必要あり
あと引数ですが JNIEnv* env, jobject thiz は必須です。
第3引数以降がネイティブメソッドの純粋な引数になります。
5.Javaからネイティブメソッド呼び出し
最後の最後の仕上げ。
Java側からネイティブメソッドを呼びだします。
▼ 成功したActivity全体のコードはこうなりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // ネイティブメソッド実行 Log.d("MainActivity", getMessage("Pisuke")); /// => Hello Pisuke from JNI!! } /** * C/C++のネイティブメソッドを宣言 **/ public native String getMessage(String msg); /** * C/C++ライブラリを読み込みさせる **/ static { System.loadLibrary("hello"); } } |
大変だったけど何とか成功・・・
これでAndroid開発でC/C++が使えるように。
煩雑とはいえ、基本手順だけ知ってれば簡単ですね。
6.C/C++側からJavaメソッドの呼び出しもできる
もちろんC/C++側からJavaメソッド呼び出しも可能
▼ Android NDKでC/C++側からJavaメソッドを呼び出す
詳しくは上記記事でもコード付きで解説しました。
必要になったらご覧ください。
ここまでのNDK導入手順まとめ
ということで手順だけを箇条書き
- C/C++ を既存プロジェクトに追加
- CMakeLists.txtにビルド設定を追加
- モジュール側のbuild.gradleを編集
- C/C++でネイティブメソッドを定義
- Javaからネイティブメソッド呼び出し
もし間違いがあればコメントからご指摘ください。
以上、Android NDK からC/C++を使う方法でした。ではまた