JNI开发基础(二)
来源:互联网 发布:人工智能的现状论文 编辑:程序博客网 时间:2024/05/29 04:35
上一篇文章讲到了C/C++端调用Android端的属性,下面接着上篇文章。
1、C/C++访问java方法:
在Android端写一个产生随机方位的随机数的方法
public int genRandomInt(int max){ Log.e("TAG","getRandomInt被调用了"); return new Random().nextInt(max); }
函数声明为:
public native void accessMethod();
JNI中函数:
extern "C"JNIEXPORT void JNICALLJava_com_sportmoo_jni01_MainActivity_accessMethod(JNIEnv *env, jobject jobj) { // jclass jclass cls = env->GetObjectClass(jobj); //jmethodId jmethodID mid = env->GetMethodID(cls, "getRandomInt", "(I)I"); //调用 jint random = env->CallIntMethod(jobj, mid, 200);}
其中,在上面得到函数id的时候,三个参数,一个是jclass,一个是Android中方法名,一个是数据类型的签名,详情见上一篇文章的最后表格,也可以利用javap函数查找。
列出所有的属性已经方法,找到需要的那个签名类型。
访问静态方法与访问方法类似,不同的是:
1、GetStaticMethodID vs GetMethodId2、CallStatic<Type>Method vs Call<Type>Method
2、C/C++访问构造函数
很多初始化工作是在构造函数函数中完成的,如果能拿到构造函数中的数据,基本上也就能拿到类中的所有方法和函数。
以Date()函数生成当前时间戳为例。
Date的构造方法就有6个,我们需要的是第一个。
extern "C"JNIEXPORT jobject JNICALLJava_com_sportmoo_jni01_MainActivity_accessConstructor(JNIEnv *env, jobject jobj) { // jclass jclass cls = env->FindClass("java/util/Date"); //jmethodId jmethodID consructor_id = env->GetMethodID(cls, "<init>", "()V"); //实例化一个Date对象 jobject date_obj = env->NewObject(cls,consructor_id); //调用getTime方法 jmethodID mid = env->GetMethodID(cls,"getTime","()J"); env->CallLongMethod(date_obj,mid); return date_obj;}
在Android中:
Date date = accessConstructor(); Log.e("TAG",date.toString());
输出结果为:
3、中文字符的处理
String中就存在这样一个转换字符格式的构造函数,C/C++中存在中文乱码的情况下就利用这个函数来进行处理。
char *c_str = "马蓉与宋江";//char c_str[] = "马蓉与宋喆";//jstring jstr = env->NewStringUTF(c_str);//执行String(byte bytes[], String charsetName)构造方法需要的条件//1.jmethodID//2.byte数组//3.字符编码jstringjclass str_cls = env->FindClass( "java/lang/String");jmethodID constructor_mid = env->GetMethodID(str_cls, "<init>", "([BLjava/lang/String;)V");//jbyte -> char //jbyteArray -> char[]jbyteArray bytes = env->NewByteArray(strlen(c_str));//byte数组赋值//0->strlen(c_str),从头到尾//对等于,从c_str这个字符数组,复制到bytes这个字符数组env->SetByteArrayRegion(bytes, 0, strlen(c_str), c_str);//字符编码jstringjstring charsetName = env->NewStringUTF("GB2312");//调用构造函数,返回编码之后的jstringreturn env->NewObject(env,str_cls,constructor_mid,bytes,charsetName);
4、传递数组
5、返回数组
创建一个指定大小的数组
jintArray jint_arr = (*env)->NewIntArray(env, len);jint *elems = (*env)->GetIntArrayElements(env, jint_arr, NULL); int i = 0;for (; i < len; i++){ elems[i] = i;}//同步(*env)->ReleaseIntArrayElements(env, jint_arr, elems, 0); return jint_arr;
6、JNI引用变量
引用变量分为局部引用和全局引用。
局部引用能够通过DeleteLocalRef手动释放对象。1、访问一个很大的java对象,使用完之后,还要进行复杂的耗时操作。2、创建了大量的局部引用,占用了太多的内存,而且这些局部引用跟后面的操作没有连续性。env->DeleteLocalRef(obj);
全局引用
共享(可以跨多个线程),手动控制内存使用。创建:函数体外: jstring global_str;函数体内: jstring obj = env->NewStringUTF("dfadfadfa"); global_str = env->NewGlobalRef(obj);可以通过不同的函数去获得或者释放:return global_str;//获得env->DeleteGlobal_str;//释放
7、弱全局引用
节省内存,在内存不足时可以释放所引用的对象。
创建NewWeakGlobalRef,销毁DeleteGlobalWeakRef。
8、异常处理
1、保证Java代码可以运行
2、补救措施保证C代码继续运行
JNI自己抛出的异常,在Java层无法被捕捉,只能在C层清空,用户通过ThrowNew抛出的异常,可以在Java层捕捉。
jclass cls = (*env)->GetObjectClass(env, jobj);jfieldID fid = (*env)->GetFieldID(env, cls, "key2", "Ljava/lang/String;");//检测是否发生Java异常jthrowable exception = (*env)->ExceptionOccurred(env);if (exception != NULL){ //让Java代码可以继续运行 //清空异常信息 (*env)->ExceptionClear(env); //补救措施 fid = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");}//获取属性的值jstring jstr = (*env)->GetObjectField(env, jobj, fid);char *str = (*env)->GetStringUTFChars(env, jstr, NULL);//对比属性值是否合法if (_stricmp(str, "super jason") != 0){ //认为抛出异常,给Java层处理 jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); (*env)->ThrowNew(env,newExcCls,"key's value is invalid!");}
9、缓存策略
局部静态变量。
10、初始化全局变量
jfieldID key_fid;jmethodID random_mid;JNIEXPORT void JNICALL Java_com_example_jni_JniTest_initIds(JNIEnv *env, jclass jcls){ key_fid = (*env)->GetFieldID(env, jcls, "key", "Ljava/lang/String;"); random_mid = (*env)->GetMethodID(env, jcls, "genRandomInt", "(I)I");}
Android加载动态库的时候,就进行初始化
static{ System.loadLibrary("jni_study"); initIds(); }
- JNI开发基础(二)
- Jni开发基础入门(二)
- JNI开发基础(一)
- JNI编程基础(二)——Android Studio NDK开发
- JNI初探二(windows平台开发)
- JNI/NDK开发指南(二)
- [JNI] 开发基础 (2) 指针
- JNI开发基础入门系列(一)
- Jni基础开发入门(三)
- Jni基础开发入门(四)
- Jni基础开发入门(五)
- Jni基础开发入门(六)
- [JNI] 开发基础(3)指针操作
- [JNI] 开发基础(5)内存分配
- [JNI] 开发基础(7)结构体
- Android JNI开发基础
- Android基础--jni开发
- Android JNI开发基础
- CSU~1328: 近似回文词(模拟)
- 感知机(perceptron)算法与MATLAB实现
- python2,python3子类调用父类初始化函数的方法和注意事项
- 点击按钮,div发生各种样式变化
- mysql修改root密码
- JNI开发基础(二)
- linux route命令详解
- 安卓开发路线图
- ansible-playbook简介
- [UVA816] Abbott's Revenge BFS
- UE4 AIController的位置问题
- javascript callback函数的理解与使用
- js判断对象构造函数
- 动态代理