今回のエンジニアブログを担当する村田です。
Cocos2d-xにおいてAndroidのネイティブ連携に必要なJNI(Java Native Interface)についてです。
JNIは、Javaで記述されたプログラムと、C/C++といった他の言語で記述されたネイティブコードを連携するための仕様です。
Cocos2d-xにおいては、
- C/C++ から Java(Android) を呼び出す時
- Java(Android) から C/C++ を呼び出す時
に用いられます。
Cocos2d-xのソースを見ながら、JNIの基本的な部分を説明します。
※ 参照バージョン:cocos2d-x-2.1.5
今回は、『Java から C/C++のメソッドを呼び出す』です。
1. nativeメソッドの定義
呼び出すC/C++側の関数をJavaプログラムに定義します。
今回使用するJavaプログラムは
- パッケージ名「com.example.testjni」
- クラス名 「TestJniActivity」
と付けます。
TestJniActivity.java
package com.example.testjni; : (略) : public class TestJniActivity extends Cocos2dxActivity { private static final String TAG = TestJniActivity.class.getSimpleName(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); : 必要な処理を記述 : } // Cocos2d-xでビルドするとlibgame.soが生成されます // libgame.soを読み込みます static { System.loadLibrary("game"); } // 呼び出すネイティブ関数 public native String getSumJni(int x, int y); public void methodTest() { // ネイティブ関数を呼び出す String val = getSumJni(1, 6); Log.d(TAG, val); } }
ポイント
- C/C++の関数を定義する際は native を付ける
2. nativeプログラムの実装
Javaから呼び出される関数は、System.loadLibraryで読み込まれたライブラリ内に実装されている必要があります。
Cocos2d-xの場合、C/C++で記述したプログラムは全てlibgame.soに含まれます。
ゆえに、あまり意識しなくても良いというのが利点です。
では今回は、簡単にmain.cppに実装します。
main.cpp
#include <jni.h> : (略) : jstring Java_com_example_testjni_TestJniActivity_getSumJni(JNIEnv* env, jobject thiz, jint x, jint y) { int sum = (int)x + (int)y; char buf[256]; sprintf(buf, "%d", sum); return env->NewStringUTF(buf); }
ポイント
- Javaとネイティブでは型が異なります
Java ネイティブ boolean jboolean byte jbyte char jchar short jshort int jint long jlong float jfloat double jdouble String jstring Object jobject ※ 配列なども記述が異なります。詳細は次回記載します。
- 関数は次の規則に沿って定義
・Java_パッケージ名_クラス名_関数名
※ パッケージ名の"."は"_"に置き換えること
・第一引数、第二引数はお決まり。第三引数からが定義した関数の引数
今回は、ネイティブコードをmain.cppに記述しましたが、メンテナンスなどを考慮すると目的別に専用のクラスを作成した方が良いです。
次回は、C/C++からJavaのメソッドを呼び出す部分について記載します。