この投稿はモバイルファクトリー Advent Calenaderの20日目のものです。
この記事ではcocos2d-x 3系で、何かと面倒で忘れがちなJNI記法・使用例を記述していきます。
JNIとは
Java Native Interface (JNI) は、Javaプラットフォームにおいて、Javaで記述されたプログラムと、他の言語(たとえばCやC++など)で書かれた、実際のCPUの上で動作するコード(ネイティブコード)とを連携するためのインタフェース仕様である。
wikipediaより引用
メソッドシグネチャ
シグネチャとは
引数の型、引数の数、メソッド名の組み合わせを組み合わせをシグネチャ(シグニチャ)と呼びます。
型対応表
java | 型のシグネチャ |
---|---|
void | V |
byte | B |
boolean | Z |
char | C |
short | S |
int | I |
long | J |
double | D |
float | F |
String | Ljava/lang/String; |
その他javaクラス | L + パッケージ/クラス名 + ; |
メソッドシグネチャ例
c++ | シグネチャ例 |
---|---|
void hoge(); | "()V" |
void hoge(int a); | "(I)V" |
int hoge(int a) | "(I)I" |
int hoge(int a, int b) | "(II)I" |
long hoge(short a, double b) | "(SD)J" |
boolean hoge(String a); | "(Ljava/lang/String;)Z" |
boolean hoge(int a[], char b, byte c[] ) | "([ab[c)Z" |
記法
"(引数)返り値"
- 引数がない場合未指定
- 引数を複数持たせる場合、連続してシグネチャを記述する
- 配列はシグネチャの前に
[
を記述する
より詳細な情報はOracleのJNI仕様などを見ると良いかと思います。
JNIの記述例は下記サイトが解りやすくまとまっています。
JNIサンプル集 : 技術者のたまごブログ
cocos2d::JniHelper
cocos2d::JniHelperを利用した記述例を記載していきます。
記法
JniHelperのドキュメントが見当たらなかったのですが、基本的にはJNIの関数なので気にしないことにします。
cocos2d::JniMethodInfo methodInfo;
if (cocos2d::JniHelper::getStaticMethodInfo(methodInfo, "名前空間/クラス名", "関数名", "メソッドシグネチャ"))
{
// メソッド呼び出し
methodInfo.env->CallxxxMethod...
// 開放処理
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
インスタンスメソッドも呼べると思うのですが、どうもうまく叩けず...
今回はjava側がstaticメソッドとしたサンプルを作成します。
cocos2d::JniHelper使用例
- void hoge();
cocos2d::JniMethodInfo methodInfo;
if (cocos2d::JniHelper::getStaticMethodInfo(methodInfo, "JAVA_CLASS_NAME", "hoge", "()V"))
{
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
- void hoge(int a, int b);
cocos2d::JniMethodInfo methodInfo;
if (cocos2d::JniHelper::getStaticMethodInfo(methodInfo, "JAVA_CLASS_NAME", "hoge", "(II)V"))
{
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, 1, 2);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
- String hoge();
std::string ret;
cocos2d::JniMethodInfo methodInfo;
if (cocos2d::JniHelper::getStaticMethodInfo(methodInfo, "JAVA_CLASS_NAME", "hoge", "()Ljava/lang/String;"))
{
jobject objResult = methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID);
ret = cocos2d::JniHelper::jstring2string((jstring)objResult); // jstringをstd::stringに変換
methodInfo.env->DeleteLocalRef(objResult);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
return ret;
実際には下記のようにプラットフォーム別に処理を分けて書くと思います。
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
// jni
#elif(CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
// obj-c++
#endif
おわりに
JNI周りはエラーが追いづらいので、ある程度まではコピペ生活が出来ると幸せかなと思っています。
今後も使用例は更新していきます。(サンプル集というには少ないので...
明日はmorigamixさんです!