Cocos2d-x 之使用 Jni

来源:互联网 发布:完美世界 游戏 知乎 编辑:程序博客网 时间:2024/05/21 18:35

Jni 技术

Android 里面有个 jni.h 封装了 java 代码与原生代码交互的功能,cocos2dx 在cocos/platform/android/jni下面有个jniHelper 类是对 jni 的再次封装,使用 jniHelper 能很容易地实现 c++ 代码与 java 互调。

C++ 调 Java

  • Android 端没什么特别要做的,只需要把函数定义好就行,函数分静态和实例两种。
  • Cocos 端要注意的东西就比较多,
    首先要引入相关的库,这里需要 jni.h 和 jniHelper.h 两个库,但其实 jniHelper.h 里面已经包含 jni.h 了,所以只需要包含 jniHelper.h 就行。jniHelper.h 位于
#if (CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID)#include <platform/android/jni/JniHelper.h>#endif

然后就是调 android 方法了,同样要加上平台判断预处理。

  • 声明jni方法结构体
JniMethodInfo jm;
  • 查找方法是否存在
静态方法 bool b=JniHelper::getStaticMethodInfo(jm,"完整类名“,”方法名“,”(函数参数)返回值“);实例方法 bool b=JniHelper::getStaticMethodInfo(jm,"完整类名”,“方法名”,“(函数参数)返回值”);

完整类名是指包含完整的包名,比如 org/cocos2dx/cpp/AppActivity。
函数参数及返回值指的是类型,要写 jni 里面的类型,关于 c++ 数据类型与 jni 的对应关系,请自行上网查。

  • 调用方法
    根据返回值不同调用不同的函数
  • 返回整型静态方法
jint jRes = jm.env->CallStaticIntMethod(jm.classID, jm.methodID, 函数参数);
  • 无返回值实例方法
jm.env->CallVoidMethod(类实例, jm.methodID);
  • 类实例通过调用静态方法来获得
jobject jIns = jm.env->CallStaticObjectMethod(jm.classID, jm.methodID);

Java 调 C++

  • Android 声明原生函数,只声明不用实现,实现放在 C++ 端。
public [static] native 返回值 方法名(参数);
  • Cocos 端实现原生函数
    不仅参数和返回值要和 Android 端定义的一样,函数名也有要求,函数名格式 Java_包1_包2_类名_原生函数名。比如类 Foo 有个原生函数叫 test,所在包是 org/cocos2dx/cpp,则 cocos 端实现的函数叫 Java_org_cocos2dx_cpp_Foo_test

  • Android端直接调该函数。

静态方法

// Java端public class AppActivity extends Cocos2dxActivity {    /**     * c++调java函数     * 静态方法     */    public static int nativeCallJava(String name, String filter) {        String fullName=name+"."+filter;        javaCallNative(fullName);        return 110;    }    /**     * java调c++原生函数     * 静态方法     */    public static native void javaCallNative(String packageName);}
// C++端#if CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID    //声明jni结构体    JniMethodInfo jm;    //查找java静态方法    bool b = JniHelper::getStaticMethodInfo(jm, "org/cocos2dx/cpp/AppActivity", "nativeCallJava", "(Ljava/lang/String;Ljava/lang/String;)I");    if (b)    {        //定义java字符串变量        jstring jTitle = jm.env->NewStringUTF("sound/bg");        jstring jText = jm.env->NewStringUTF("mp3");        //调用java静态方法        jint jRes = jm.env->CallStaticIntMethod(jm.classID, jm.methodID, jTitle, jText);        //资源回收        jm.env->DeleteLocalRef(jTitle);        jm.env->DeleteLocalRef(jText);        //取得java方法返回值        char name[16];        sprintf(name, "return code:%d", jRes);        this->addChild(m_tip_text);        m_tip_text->setVisible(true);        m_tip_text->setString(name);    }#endif#if CC_TARGET_PLATFORM==CC_PLATFORM_ANDROIDextern "C"{    /**    * java调原生函数    */    void Java_org_cocos2dx_cpp_AppActivity_javaCallNative(JNIEnv* env, jobject thiz, jstring name)    {        JniMethodInfo jm;        const char* cName = jm.env->GetStringUTFChars(name, NULL);        SimpleAudioEngine::getInstance()->playBackgroundMusic(cName);        SimpleAudioEngine::getInstance()->setBackgroundMusicVolume(100);        env->ReleaseStringUTFChars(name, cName);    }}#endif

实例方法

//Java端package org.cocos2dx.cpp;public class Foo{    /**     * c++调java函数     * 静态方法     * 获取类实例     */    private static Foo _ins;    public static Object getInstance() {        if (_ins == null)        {            _ins = new Foo();        }        return _ins;    }    /**     * c++调java函数     * 非静态方法     */    public int nativeCallJava() {        javaCallNative();        return 111;    }    /**     * java调c++原生函数     * 非静态方法     */    public native void javaCallNative();}
//C++端#if CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID    //声明jni结构体    JniMethodInfo jm;    //声明java类实例    jobject jIns;    //先调用静态方法获得类实例    if (JniHelper::getStaticMethodInfo(jm, "org/cocos2dx/cpp/Foo", "getInstance", "()Ljava/lang/Object;"))    {        jIns = jm.env->CallStaticObjectMethod(jm.classID, jm.methodID);        if (!jIns)        {            m_tip_text->setString("ins is null");            return;        }    }    //查找非静态方法    bool b = JniHelper::getMethodInfo(jm, "org/cocos2dx/cpp/Foo", "nativeCallJava", "()I");    if (b)    {        //调用java非静态方法        jint jRes = jm.env->CallIntMethod(jIns, jm.methodID);        jm.env->CallVoidMethod(jIns, jm.methodID);        //取得java方法返回值        char name[16];        sprintf(name, "return code:%d", jRes);        m_tip_text->setString(name);    }#endif#if CC_TARGET_PLATFORM==CC_PLATFORM_ANDROIDextern "C"{    /**    * java调原生函数    */    void Java_org_cocos2dx_cpp_Foo_javaCallNative(JNIEnv* env, jobject thiz)    {        SimpleAudioEngine::getInstance()->stopBackgroundMusic();    }}#endif
原创粉丝点击