Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
20
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

cocos2d-x JNI サンプル集

この投稿はモバイルファクトリー 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さんです!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
20
Help us understand the problem. What are the problem?