エンジニア

Cocos2d-xにおけるJNI(その2)

投稿日:2013年11月1日 更新日:

今回のエンジニアブログを担当する村田です。

前回の「Cocos2d-xにおけるJNI(その1)」の続きです。

今回は、『C/C++ から Java(Android) を呼び出す時』です。
Android端末に設定されている言語情報をC/C++側へ返すプログラムを作成します。

使用したCocos2d-xのバージョン:cocos2d-x-2.1.5

1. Javaプログラムの定義

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");
    }

    /**  
     * 言語情報を取得  
     * @return 言語情報  
     */
    public static String getLanguage() {
        // 言語情報を返す  
        return Locale.getDefault().getLanguage();
    }
}
2. nativeプログラムの実装

今回は、JNI用のファイルを作成して実装します。

DeviceJni.h

#ifndef __DEVICE_JNI_H__  
#define __DEVICE_JNI_H__  

#include <jni.h>

extern "C" {

    // 言語情報を取得  
    extern const char* getLanguageJni();

}

#endif // __DEVICE_JNI_H__  

DeviceJni.cpp

#include "DeviceJni.h"
#include "cocos2d.h"
#include "platform/android/jni/JniHelper.h"

extern "C" {

    // 言語情報を取得  
    const char* getLanguageJni()
    {
        JniMethodInfo methodInfo;

        if (! JniHelper::getStaticMethodInfo(methodInfo, "com/example/testjni/TestJniActivity", "getLanguage", "()Ljava/lang/String;"))
        {
            LOGD("Failed to find static method of getLanguageJni");
            return "";
        }
        // Javaのプログラムを呼び出す  
        jobject objResult = methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID);

        // jstringをstd::stringに変換  
        std::string ret = JniHelper::jstring2string((jstring)objResult);

        // 解放処理  
        methodInfo.env->DeleteLocalRef(objResult);
        methodInfo.env->DeleteLocalRef(methodInfo.classID);

        return ret.c_str();
    }

}

ポイント

  • Cocos2d-xには、JNIを簡単に扱うためにJniHelperクラスが存在します。
  • staticメソッドを呼び出す場合は、JniHelper::getStaticMethodInfo関数を使用します。
    インスタンスメソッドを呼び出す場合は、JniHelper::getMethodInfo関数を使用します。

    • 第1引数:JniMethodInfo構造体を渡します。
    • 第2引数:パッケージ名を含んだ形でクラスを指定します。
    • 第3引数:メソッド名を指定します。
    • 第4引数:メソッドのシグニチャを指定します。
      ※ シグニチャについては後述

    処理が正常に終了すると、JniMethodInfo構造体に必要なデータが格納されます。

  • Javaで実装されたメソッドを実行する時は、状況に応じた関数を呼び出します。
    staticメソッド インスタンスメソッド
    戻り値なし CallStaticVoidMethod CallVoidMethod
    戻り値あり
    オブジェクト型
    CallStaticObjectMethod CallObjectMethod
    戻り値あり
    プリミティブ型
    CallStaticタイプMethod
    例:CallStaticIntMethod
    CallタイプMethod
    例:CallDoubleMethod
  • 文字列を取得した場合は、jstringからstringに変換する必要があります。
    JniHelperクラスには、この変換を簡単に行ってくれるjstring2string関数があります。

あとは、この関数をC/C++から呼び出すことで、Android端末に設定されている言語情報を取得する事ができます。

シグニチャは下記のとおりになっており、最初は取っ付きにくい部分です。

Javaの型 シグニチャ
boolean Z
byte B
char C
short S
int I
long J
float F
double D
クラス Lパッケージを含めたフルパス;
例)String型 Ljava/lang/String;
配列 [シグニチャ
例)double[] → [D

2回に渡りJNIを説明してきました。

JNIを利用することでAndroidネイティブの機能を呼び出す事ができるため、アプリ内課金なども実現可能となります。

実現できる事の幅が広がりますので、覚えておいて損は無いかと思います。

採用情報

ワンダープラネットでは、一緒に働く仲間を幅広い職種で募集しております。

-エンジニア
-

© WonderPlanet Inc.