JNI中jstring 与 const char* 相互转换函数

来源:互联网 发布:石家庄seo顾问服务 编辑:程序博客网 时间:2024/05/22 23:25

在平时的工作,经常用到jni和const类型转换。


//将const char类型转换成jstring类型
jstring CStr2Jstring( JNIEnv* env, const char* pat )
{
//定义java String类 strClass
jclass strClass = (env)->FindClass("Ljava/lang/String;");
//获取java String类方法String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新String
jmethodID ctorID = (env)->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
//建立byte数组
jbyteArray bytes = (env)->NewByteArray((jsize)strlen(pat));
//将char* 转换为byte数组
(env)->SetByteArrayRegion(bytes, 0, (jsize)strlen(pat), (jbyte*)pat);
//设置String, 保存语言类型,用于byte数组转换至String时的参数
jstring encoding = (env)->NewStringUTF("GB2312");
//将byte数组转换为java String,并输出
return (jstring)(env)->NewObject(strClass, ctorID, bytes, encoding);

}

char*   Jstring2CStr(JNIEnv*   env,   jstring   jstr) 

char*   rtn   =   NULL; 
jclass   clsstring   =   env->FindClass("java/lang/String");  
jstring   strencode   =   env->NewStringUTF("GB2312"); 
jmethodID   mid   =   env->GetMethodID(clsstring,   "getBytes",   "(Ljava/lang/String;)[B");  
jbyteArray   barr=   (jbyteArray)env->CallObjectMethod(jstr,mid,strencode); 
jsize   alen   =   env->GetArrayLength(barr); 
jbyte*   ba   =   env->GetByteArrayElements(barr,JNI_FALSE); 
if(alen   >   0) 

  rtn   =   (char*)malloc(alen+1);         //new   char[alen+1]; 
  memcpy(rtn,ba,alen); 
  rtn[alen]=0; 

env->ReleaseByteArrayElements(barr,ba,0); 
return rtn;

2.使用JNI默认的转换函数实现

const char *dname=NULL;
dname = env->GetStringUTFChars(devName, 0)

其中devName是Jstring类型。

建议大家用第二种方法,更跨平台。

---------------------------------------------------------------------------------例子:

1  使用的方法都在jniHelper.h中,包含吖头文件

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "platform/android/jni/JniHelper.h"                                    //(ctrl+F)
#endif

2  java调用C++

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) 
 extern "C"
 {
  //  1.Java_com_newtest2_jniHelper_SendInfo  ”Java”开头   ”com_nretest2”为包名  ”jniHelper”为对应的java文件  ”SendInfo”为对应的方法  使用”_”连接
  //  2.(JNIEnv *env, jobject thiz, jstring info) 前2个为自带参数, 其余jstring info为自己的参数   出来弹出框 就Ok
  void  Java_com_u58_cocosgame_DDZ2_nativeLogin(JNIEnv* env, jobject thiz, jstring name, jstring pass)
  {
   const char *_name = env->GetStringUTFChars(name, 0) ;  //类型转换
    
   const char* _pass = env->GetStringUTFChars(pass, 0);

   MessageBox( _name, _pass);
   
  }
 }
#endif
//}

3  C+++条用java

void  LoginScene::test_Java()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)    //断设备是否为Android设备,如
 __android_log_print(ANDROID_LOG_ERROR, "LoginScene", "LoginScene::test_Java()");

 JniMethodInfo minfo;
 jobject jobj;

 //if (GETGAMEJAVAINSTANCE)  //JniHelper::getStaticMethodInfo(minfo, "com/u58/cocosgame/DDZ2","getInstance3","()Lcom/u58/cocosgame/DDZ2;")

//拿到类对象   与方法是静态与...

if(GETGAMEJAVAINSTANCE)
 {
  //调用Java静态函数,取得对象。 
  __android_log_print(ANDROID_LOG_ERROR, "LoginScene", "LoginScene::test_Java() 1");

  jobj = minfo.env->CallObjectMethod(minfo.classID, minfo.methodID);
  if (jobj != NULL)
  {
   __android_log_print(ANDROID_LOG_ERROR, "LoginScene", "LoginScene::test_Java() 2");
   jstring jname = minfo.env->NewStringUTF("this is name");
   jstring jpass = minfo.env->NewStringUTF("this is password");          //类型转换
 
   if (JniHelper::getMethodInfo(minfo, GAMEPACKAGE, "test_Java", "(Ljava/lang/String;Ljava/lang/String;)V")) // ()V  参数+返回值
   {
    __android_log_print(ANDROID_LOG_ERROR, "LoginScene", "LoginScene::test_Java() 3");
    //调用java非静态函数, 参数1:Java对象,上面已经取得   参数2:方法ID 
    //minfo.env->CallVoidMethod(jobj, minfo.methodID,jms); 
    minfo.env->CallVoidMethod(jobj, minfo.methodID, jname,jpass);     //???  voidMethod2
    log("test_Java succeed");
    minfo.env->DeleteLocalRef(jname);   //清楚空间
    minfo.env->DeleteLocalRef(jpass);
    return;
   }
   else
   {
    log("test_Java1 Fail1");
   }
  }
  else
  {
   log("test_Java1 Fail2");
  }
 }
 else
 {
  log("test_Java1 Fail3");
 }
#endif

}

例子二:

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) 
 //getStaticMethodInfo,判断Java静态函数是否存在,并且把信息保存到minfo里 
 //参数1:JniMethodInfo 
 //参数2:Java类包名+类名 
 //参数3:Java函数名称 
 //参数4:函数参数类型和返回值类型,这里的返回值类型是HelloCpp类的对象。写法:L+包名+; 其他的类型请看上面的“JNI详细教程” 

 JniMethodInfo minfo; 
 jobject jobj; 
 if(GETGAMEJAVAINSTANCE)
 { 
  //调用Java静态函数,取得对象。 
  jobj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID); 
  if (jobj != NULL) 
  { 
   jlong  jms = lYuanbao;
   if(JniHelper::getMethodInfo(minfo,GAMEPACKAGE,"AliPayYuanbao","(J)V"))
   { 
    log("Startpay");
    //调用java非静态函数, 参数1:Java对象,上面已经取得   参数2:方法ID 
    //minfo.env->CallVoidMethod(jobj, minfo.methodID,jms); 
    minfo.env->CallVoidMethod(jobj, minfo.methodID,jms); 
    log("Startpay suc");
    return;
   } 
   else
   {
    log("Startpay ...................

....
#endif
}------------------------------------------------------------------------

1  alipay支付宝库,eclispe没有。不会导入;
头: 1 删除旧的   2 导入新的(how 我死活不会,/因为选不中)  3刷新 4 再次导入(property--android-d导入)

2      <uses-sdk android:minSdkVersion="10"/> 这个是SDk版本
Android SDk manager中又对用的最小Android操作系统,比高的都能玩

3          <activity android:name="com.u58.FlightChess.MobileTBFlightChess"
这个不是应用名字, 修改是在string.xml中。 (eciplse中res--values---)

4 NDK :是java C++ 之间桥梁。 SDk:是开发Java的。。。
5 编译运行后: 会在 lib  bin  生成APK  + 。so
  jni文件夹下Android.mk修改这不用说,把自己工程要编译的写上去。
6
  不管C++ java 水貂用水都要做JNI类型转换。
 
4 我问是不是导入VS中:  真是傻逼 VS eclipse啥关系;没关系

 

.mk 是makeFile
A LOCAL_MODULE_FILENAME := libcocosgame  模块名字(库的名字)
整个C++/cocos2d-x都要用NDK编译。 就是生成的DDZ2.java中。
B  用到了写,没用到。。。
 LOCAL_SRC_FILES    NDK编译时用到的源文件
 LOCAL_C_INCLUDES   NDK编译时依赖的头文件
 LOCAL_WHOLE_STATIC_LIBRARIES   依赖的静态库
 $(call import-add-path,$(LOCAL_PATH)/../../cocos2d/external)  编译头文件时,找不到会从这些去寻找; 你注释一个试试 crash
 #LOCAL_STATIC_LIBRARIES := cocos2dx_static  这是注释
 LOCAL_MODULE_FILENAME    模块名字
 $(call my-dir)的作用就是返回当前目录的路径。

 C
 NDk    : 是编译C++代码
 eclipse: 编译java代码
 D:
  CoupleDDZ 是工程文件。  libcocos2d是cocos库文件;
  编译时顺序: libcocos2d ---->JNI部分 ---》java本身的代码    都没有问题才会生成APK

 

0 0
原创粉丝点击