させす技術メモ(自家用)

主にAnroid開発を行うSEの技術メモ。サーバ、iOSにも手を出していくよ。

Android Studio 2.2でC++のコードを使う

AndroidC++コード使うのは結構めんどくさかったんだけど、 先日リリースされたAndroid Studio 2.2以降だと割と手軽にC++コードを混ぜ込めるようなので、

やってみた。

そのメモ。


まずは公式を参照。

Add C and C++ Code to Your Project | Android Studio

Gradleに詳しくないので、これだけ読んでもあんまり理解できなかったのですが、
要するに、

Android Studioのバージョンを2.2~にして、

・最新の、NDK
・CMake
・LLDB

以上3点をインストールしておけばよいということみたいです。
特にNDKは最新にしないとエラー吐いてビルド通らなくなるので要注意です。

ここまで用意したら、新規プロジェクトを立ち上げます。

まずはNew Project画面で、include C++ supportにチェックします
f:id:sansensui:20170129132554p:plain

それからAPIレベルなどをいつも通りに設定していくと、Activity設定画面の次に、以下のような画面が表示されます。

f:id:sansensui:20170129132610p:plain

C++の設定です。
が、まずはデフォルトのまま進みます。

 ※ここらは上記の公式サイトの「C / C++ のサポートを使用した新しいプロジェクトの作成」の項に説明があります。

出来上がったプロジェクトを見ると、

C++を呼ぶJava側のコード

package com.test.www.myapplication;

import android.support.v7.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");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
}

■呼び出されるC++コード

#include <jni.h>
#include <string>

extern "C"
jstring
Java_com_test_www_myapplication_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

javaからC++のコードを呼び出している仕組みは見ての通り。
こっから独自のネイティブメソッドを定義するに際して、ポイントとなるのは以下6点ほど。

①呼び出し元Javaに"native"宣言してメソッド定義

②"native"宣言したjavaメソッドに対し、C++ソースでは「java側のパッケージ名_メソッド名」でメソッドを定義する
 ★このルールに従わないとメソッドが認識されない

 例)
  ・Package名:com.test.www
  ・Method名:callTest
  ならば、
  ・C++ Method名:com_test_www_callTest
  で定義する

Javaから呼び出されるnativeメソッドの第一引数のJNIEnv *env、第二引数のjobjectは固定。
 必要な引数がある場合は、第三以降に書く

javaからコールする関数名の前にextern “C"をつける
 ※C++コードをCのコードで解釈させる

⑤補足だが、文字列の扱い方がJavaC++では異なるので、
  C++内部ではstd::stringで扱い、Javaに帰すときにjstring形式で返す

  ※変換方法は env->NewStringUTF(文字列.c_str());

C++内部のコードを修正した場合、
 1.Make projectでビルドする
 2.Refresh Linked C++ Projectsを実施する(念のため)
 3.あとは普通にRun

 の作業を必ず行う。


昔のAndroid NDKは本当に手順がめんどくさいと聞いていますが、
たったこれだけのことでプロジェクト作れるし、
あと、C++のコードにブレーク打ってデバッグもできるので、かなり使いやすくなってると思います。

上には書かなかったけど、 C++のファイルを追加する場合は、追加したファイルを読みこませるための設定をCmakeLists.txtに追記する必要がある。

f:id:sansensui:20170129160920p:plain

単純に書けばこうなる。 でもCmakeはもう少し便利に使えるらしい。

まあ今はとりあえず動けばよいか。。 C++に関してまだまだにわかなので、これから勉強する(´・ω・`)