cocos2d-x中有一个JniHelper类详细使用

cocos2d-x中有一个JniHelper类详细使用,第1张

概述主体思路 通过JNI获取java虚拟机,再获取当前程序的JNI环境,通过JNI环境获取需要调用的java类信息,再获取需要调用的java类中的函数信息。再通过JNI环境调用,使用类信息、函数信息,调用对应的java函数。 看起来好像有点复杂,but不用担心,cocos2d-x中有一个JniHelper类(头文件的copyright为:cocos2d-x.org,是Google提供的还是cocos2 主体思路

通过JNI获取java虚拟机,再获取当前程序的JNI环境,通过JNI环境获取需要调用的java类信息,再获取需要调用的java类中的函数信息。再通过JNI环境调用,使用类信息、函数信息,调用对应的java函数。
看起来好像有点复杂,but不用担心,cocos2d-x中有一个JniHelper类(头文件的copyright为:cocos2d-x.org,是Google提供的还是cocos2d-x小组自己封装的我就不清楚了),它已经把这些工作封装好了。

JniHelper类的使用

加入如下头文件:

#include "platform/androID/jni/JniHelper.h"

需要使用的接口如下:

static bool getStaticmethodInfo(JniMethodInfo &methodinfo,const char *classname,const char *methodname,const char *paramCode);static bool getmethodInfo(JniMethodInfo &methodinfo,const char *paramCode);

实现上我们只需要使用上面这两个接口,就可以获取java类的所有函数信息了。JNI环境的获取、各种错误处理都已经在这两个接口实现中封装好了。
先上代码,再来依次讲解每个参数的意义和使用方法:

    //函数信息结构体    JniMethodInfo minfo;    bool isHave = JniHelper::getStaticmethodInfo(minfo,/*JniMethodInfo的引用*/                                                 "com/omega/MyApp",/*类的路径*/                                                 "getJavaActivity",/*函数名*/                                                 "()Ljava/lang/Object;");/*函数类型简写*/    jobject activityObj;    if (isHave)    {        //CallStaticObjectMethod调用java函数,并把返回值赋值给activityObj        activityObj = minfo.env->CallStaticObjectMethod(minfo.classID,minfo.methodID);    }

OK,很简单。上面的代码,就是使用JNI在C++中调用java类静态函数的典型使用方法。只有两步:

1. 获取java函数的信息,classID、methodID等等 2. 选择jnienv中的接口,进行函数调用 getStaticmethodInfo参数详解

两个接口的参数一样,意义也相同,详解如下:
JniMethodInfo &methodinfo JniMethodInfo对象的引用,函数执行中会把jnIEvn、classID、methodID写入到引用中。
const char *classname 类的路径,把类的完整包名写全,用法如以上代码。
const char *methodname 函数名,函数名写上就行了。

@H_301_40@const char *paramCode 函数类型简写
这个参数需要单独介绍,它的格式为:(参数)返回类型。
例如:无参数,voID返回类型函数,其简写为 ()V
java中的类型对应的简写如下:

@H_502_51@ 参数简写 char short int long float double voID Object Array
参数类型
boolean Z
byte B
C
S
I
J
F
D
V
Ljava/lang/String; L用/分割类的完整路径
[Ljava/lang/String; [签名 [I

@H_301_40@多参数的函数
如果函数有多个参数,直接把简写并列即可。注意Object与Array型参数简写结尾的分号,示例:
IIII //4个int型参数的函数
ILjava/lang/String;I //整形,string类型,整形组合 (int x,String a,int y)

通过jnienv进行函数调用

JNIEvn有一系列的CallStatic[返回类型]Method、Call[返回类型]Method接口,需要针对不同的函数返回类型选择调用。
[返回类型]以函数返回类型的不同,对应不同的函数名。
例如:
CallStaticVoIDMethod ———voID
CallVoIDMethod ———voID
其对应关系如下:

函数名 @H_502_51@ 函数返回值类型 VoID jobject Boolean Byte Char Short Int Long float Double
voID
jboolean
jbyte
jchar
Jshort
jint
jlong
jfloat
jdouble

@H_301_40@参数传递
调用有参数的java函数时,需要把对应的参数传递进去。需要把参数按顺序加入到classID、methodID后面,并且需要做类型转换。例如:

jint jX = 10;jint jY = 10;minfo.env->CallStaticVoIDMethod(minfo.classID,minfo.methodID,jX,jY);

参数类型转换关系如下:

C++类型 @H_502_51@ java类型 jdouble Class String Object[] boolean[] byte[] char[] short[] int[] long[] float[] double[]
jclass
Jstring
jobjectArray
jbooleanArray
jbyteArray
jchararray
JshortArray
jintArray
jlongArray
jfloatArray
jdoubleArray

@H_301_40@string类型的转换
实际上我们最常用的参数类型,主要是内建的数据类型、string字符串类型。数据类型可以直接转为j类型,但是string类型需要做如下处理:

Jstring jmsg = minfo.env->NewStringUTF("http://www.baIDu.com");minfo.env->CallStaticVoIDMethod(minfo.classID,jmsg);
非静态函数的调用

非静态函数的调用与静态函数的调用类型,但是需要通过一个静态函数获取java类对象。
示例:

//C++代码    //1. 获取activity静态对象    JniMethodInfo minfo;    bool isHave = JniHelper::getStaticmethodInfo(minfo,"com/omega/MyApp","getJavaActivity","()Ljava/lang/Object;");    jobject activityObj;    if (isHave)    {        //调用静态函数getJavaActivity,获取java类对象。        activityObj = minfo.env->CallStaticObjectMethod(minfo.classID,minfo.methodID);    }    //2. 查找displayWebVIEw接口,获取其函数信息,并用jobj调用    isHave = JniHelper::getmethodInfo(minfo,"displayWebVIEw","(IIII)V");     if (!isHave)    {        cclog("jni:displayWebVIEw 函数不存在");    }    else    {        //调用此函数        jint jX = (int)tlX;        jint jY = (int)tlY;        jint jWIDth = (int)webWIDth;        jint jHeight = (int)webHeight;        //调用displayWebVIEw函数,并传入参数        minfo.env->CallVoIDMethod(activityObj,jY,jWIDth,jHeight);    }
详尽的示例代码

最后,放一块比较详细的JNI使用代码,基本上覆盖了的全部使用情况。

    JniMethodInfo minfo;//JniHelper       /* 测试用方法 */     /*bool isHave = JniHelper::getStaticmethodInfo(minfo,"com/cocoa/HiWorld","loginGree","()V"); //     if (isHave) {     //cclog("有showtext ");     minfo.env -> CallStaticVoIDMethod(minfo.classID,minfo.methodID);     }else     {     //cclog("没有方法showtext");     }*/    /* 分享 */    /*//将c++中的string转换成java中的string     //char str[] = "test";     bool isHave = JniHelper::getStaticmethodInfo(minfo,"shareSina","(Ljava/lang/String;Ljava/lang/String;)V"); //     if (isHave) {     //cclog("有share ");     Jstring Jstr = minfo.env->NewStringUTF("test1 share");     Jstring Jst = minfo.env->NewStringUTF("/data/data/com.cocoa/cy.png");      //Jstring Jst = minfo.env->NewStringUTF("");     minfo.env -> CallStaticVoIDMethod(minfo.classID,Jstr,Jst);     }else     {     //cclog("没有方法share");     }*/    /* 设置高分 */    /*jint ind = 0;     jlong lsre = 2202l;     bool isHave = JniHelper::getStaticmethodInfo(minfo,"setHighscore","(IJ)V");      if (isHave) {     minfo.env -> CallStaticVoIDMethod(minfo.classID,ind,lsre);                 }*/    /* 成就解锁 */    /*jint aind = 0;     bool isHave = JniHelper::getStaticmethodInfo(minfo,"unLock","(I)V");      if (isHave) {     minfo.env -> CallStaticVoIDMethod(minfo.classID,aind);                 }*/    /* 测试用方法 */     bool isHave = JniHelper::getStaticmethodInfo(minfo,"rtnActivity","()Ljava/lang/Object;");    jobject jobj;    if (isHave) {         jobj = minfo.env->CallStaticObjectMethod(minfo.classID,minfo.methodID);     }           //cclog(" jobj存在");     /* 测试用方法,非静态无参数无返回值方法 */    /*isHave = JniHelper::getmethodInfo(minfo,"showtext","()V");      if (isHave) {     minfo.env -> CallVoIDMethod(jobj,minfo.methodID);     }*/    /* 测试用方法,非静态有java类型的String参数无返回值方法 */    /*isHave = JniHelper::getmethodInfo(minfo,"(Ljava/lang/String;)V");      if (isHave) {     Jstring jmsg = minfo.env->NewStringUTF("msg okey!");     minfo.env -> CallVoIDMethod(jobj,jmsg);     }*/    /* 测试用方法,返回java类型的String,有java类型的String和int参数方法 */    /*isHave = JniHelper::getmethodInfo(minfo,"(Ljava/lang/String;I)Ljava/lang/String;");      if (isHave) {     Jstring jmsg = minfo.env->NewStringUTF("msg okey! return string");     jint index = 0;     minfo.env -> CallObjectMethod(jobj,jmsg,index);     }*/    /* 测试用方法,返回java类型的String[],有java类型的String[]和int参数方法 */    /*isHave = JniHelper::getmethodInfo(minfo,"([Ljava/lang/String;I)[Ljava/lang/String;");      if (isHave) {     jobjectArray args = 0;     Jstring str;     Jsize len = 5;     const char* sa[] = {"Hi,","World!","JNI ","is ","fun"};     int i = 0;     args = minfo.env->NewObjectArray(len,minfo.env->FindClass("java/lang/String"),0);     for(i=0;iNewStringUTF(sa[i]);     minfo.env->SetobjectArrayElement(args,i,str);     }     //minfo.env->GetStringArrayRegion(args,10,buf);     //jintArray jmsg = {1,2,3};     //minfo.env->NewStringUTF("msg okey! return string");     jint index = 0;     minfo.env -> CallObjectMethod(jobj,args,index);     }*/    /* 测试用方法,无返回类型,有java类型的int[]和int参数方法 */    /*isHave = JniHelper::getmethodInfo(minfo,"testArr","([II)V");      if (isHave) {     jint buf[]={7,5,8,9,3};     jintArray jintArr; //定义jint数组     jintArr = minfo.env->NewIntArray(5);     minfo.env->SetIntArrayRegion(jintArr,buf);     jint index = 0;     minfo.env -> CallVoIDMethod(jobj,jintArr,index);     }*/    /* 测试用方法,无返回类型,有java类型的byte[]和int参数方法 */    isHave = JniHelper::getmethodInfo(minfo,"([BI)V");     if (isHave) {        jbyte buf[]={7,3};        jbyteArray jbyteArr; //定义jbyte数组        jbyteArr = minfo.env->NewByteArray(5);        minfo.env->SetByteArrayRegion(jbyteArr,buf);        jint index = 0;        minfo.env -> CallVoIDMethod(jobj,jbyteArr,index);    }
private static HiWorld hiWorld = null;protected voID onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    hiWorld = this;    if (detectopenGLES20()) {        // get the packagename,it's used to set the resource path        String packagename = getApplication().getPackagename();        super.setPackagename(packagename);        // set content        setContentVIEw(R.layout.game_demo);        getwindow().setFeatureInt(Window.FEATURE_CUSTOM_Title,R.layout.window_Title);        mGLVIEw = (Cocos2dxGLSurfaceVIEw) findVIEwByID(R.ID.game_gl_surfacevIEw);        mGLVIEw.setTextFIEld((Cocos2dxEditText) findVIEwByID(R.ID.textFIEld));        mGLVIEw.setEGLContextClIEntVersion(2);        mGLVIEw.setCocos2dxRenderer(new Cocos2dxRenderer());        task = new TimerTask() {            @OverrIDe            public voID run() {                // HiWorld.shoot(hiWorld);                Log.e("-------------------","-------------------");                // 调用c++中的方法                System.out.println("------------------------"                                   + stringZjy1());            }        };        timer = new Timer();        timer.schedule(task,5000);    } else {        Log.d("activity","don't support gles2.0");        finish();    }    static {        System.loadlibrary("game");    }    // c++中調用的方法    public static Object rtnActivity() {        System.out.println("----------rtnActivity");        return hiWorld;    }    // c++中調用的方法,传String类型    public voID showtext(final String msg) {         // 添加到主线程        hiWorld.runOnUiThread(new Runnable() {            public voID run() {                 System.out.println("----------msg:"+msg);            }        });    }    //c++中調用的方法,传String类型和int类型    public String showtext(final String msg,final int index) {         // 添加到主线程        hiWorld.runOnUiThread(new Runnable() {            public voID run() {                 System.out.println("----------msg:"+msg+"; index="+index);            }        });        return "okey String showtext(final String msg,final int index)";    }    //c++中調用的方法,传String[]类型和int类型    public String[] showtext(final String[] msg,final int index) {         String[] strArr = {"1","2","3","4","5"};        // 添加到主线程        hiWorld.runOnUiThread(new Runnable() {            public voID run() {                 for(String _str:msg){                    System.out.println("----------String[] msg:"+_str+"; index="+index);                }            }        });        return strArr;    }    //c++中調用的方法,传int[]类型和int类型    public voID testArr(final int msg[],final int index) {         // 添加到主线程        hiWorld.runOnUiThread(new Runnable() {            public voID run() {                 System.out.println("----------int[] msg len:"+msg.length);                for(int _bl:msg){                    System.out.println("----------int[] msg:"+_bl+"; index="+index);                }            }        });    }    //c++中調用的方法,传int[]类型和int类型    public voID testArr(final byte msg[],final int index) {         // 添加到主线程        hiWorld.runOnUiThread(new Runnable() {            public voID run() {                 System.out.println("----------byte[] msg len:"+msg.length);                for(int _bl:msg){                    System.out.println("----------byte[] msg:"+_bl+"; index="+index);                }            }        });    }
总结

以上是内存溢出为你收集整理的cocos2d-x中有一个JniHelper类详细使用全部内容,希望文章能够帮你解决cocos2d-x中有一个JniHelper类详细使用所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1066146.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-26
下一篇2022-05-26

发表评论

登录后才能评论

评论列表(0条)

    保存