您的位置:首页 > Web前端 > JavaScript

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

2015-12-18 16:17 579 查看
在平时的工作,经常用到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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: