(三)JNI常用示例
针对我之前文章的练习:JNI方法总结
1. 字符串
JAVA层:
test.testString("HELLOWORLD");
JNI层:
JNIEXPORT jstring JNICALL Java_com_aplex_canopen_CANopen_testString(JNIEnv *env, jobject obj, jstring str){jboolean isCopy;const char *cstr = env->GetStringUTFChars(str, &isCopy); //这个是把android默认的Unicode编码转换为UTF-8编码,然后得到数据if(isCopy==JNI_FALSE){LOGD("错误");} else if(isCopy==JNI_TRUE){LOGD("正确");}LOGD("UTF-8数据为:%s", cstr);LOGD("UTF-8数据长度为:%d", env->GetStringUTFLength(str));LOGD("Unicode数据长度为:%d", env->GetStringLength(str));env->ReleaseStringUTFChars(str, cstr);std::string strin = "hello world";return env->NewStringUTF(strin.c_str()); //生成一个新的UTF-8格式字符串 }
结果:
D/Canopencommand: 正确 D/Canopencommand: UTF-8数据为:HELLOWORLD D/Canopencommand: UTF-8数据长度为:10D/Canopencommand: Unicode数据长度为:10
2. 基本类型数组
java层:
test.testArray(new int[]{1,2,3,4,5,6,7,8,9});
JNI层:
JNIEXPORT void JNICALL Java_com_aplex_canopen_CANopen_testArray(JNIEnv *env, jobject obj, jintArray arr){jboolean isCopy;LOGD("######基本类型数组测试#########");//1. 拿到数组长度jint len = env->GetArrayLength(arr);LOGD("数组长度为:%d",len);//2. 拿到数组方法一:也就是转成可用的int*jint* val = env->GetIntArrayElements(arr, &isCopy);if(isCopy){LOGD("数组元素为");for (int i = 0; i < len; ++i) {LOGD("元素%d:%d",i,val[i]);}}//3. 拿到数组方法二:拿指定长度数组 jint val1[len];env->GetIntArrayRegion(arr, 0, len, val1); //0:起始索引; len: 长度; buf:需要放入的地方LOGD("数组元素1为");for (int i = 0; i < len; ++i) {LOGD("元素%d:%d",i,val1[i]);} }
结果
D/Canopencommand: ######基本类型数组测试######### D/Canopencommand: 数组长度为:9 D/Canopencommand: 数组元素为 D/Canopencommand: 元素0:1 D/Canopencommand: 元素1:2 D/Canopencommand: 元素2:3 D/Canopencommand: 元素3:4 D/Canopencommand: 元素4:5 D/Canopencommand: 元素5:6 D/Canopencommand: 元素6:7 D/Canopencommand: 元素7:8 D/Canopencommand: 元素8:9 D/Canopencommand: 数组元素1为 D/Canopencommand: 元素0:1 D/Canopencommand: 元素1:2 D/Canopencommand: 元素2:3 D/Canopencommand: 元素3:4 D/Canopencommand: 元素4:5 D/Canopencommand: 元素5:6 D/Canopencommand: 元素6:7 D/Canopencommand: 元素7:8 D/Canopencommand: 元素8:9
3. 对象类型数组
JAVA层:
test.testArrayObject(new String[]{"haha","hehe","wawa","dada"});
JNI层:
JNIEXPORT void JNICALL Java_com_aplex_canopen_CANopen_testArrayObject(JNIEnv *env, jobject obj, jobjectArray strArr){jboolean isCopy;LOGD("######对象类型数组测试#########");int len = env->GetArrayLength(strArr); //拿到数组长度//1. 拿到对象数组数据for (int i = 0; i < len; ++i) {jstring str = (jstring)env->GetObjectArrayElement(strArr, i); //拿到对象数组的元素:注意要强制转换const char *cstr = env->GetStringUTFChars(str, &isCopy);LOGD("字符串%d为:%s",i,cstr);env->ReleaseStringUTFChars(str, cstr);}//2. 设置对象数组数据jstring str = env->NewStringUTF("abcdefg");env->SetObjectArrayElement(strArr, 0, str); //修改对象数组中的数据LOGD("修改后再看一遍2");for (int i = 0; i < len; ++i) {jstring str = (jstring)env->GetObjectArrayElement(strArr, i);const char *cstr = env->GetStringUTFChars(str, &isCopy);LOGD("字符串%d为:%s",i,cstr);env->ReleaseStringUTFChars(str, cstr);}//3. 构造一个新的对象数组jclass strClass = env->FindClass("java/lang/String");jobjectArray newStr = env->NewObjectArray(len-1, strClass, 0); //创建一个新的对象数组len = env->GetArrayLength(newStr); //拿到新创立数组的长度for (int i = 0; i < len; ++i) {jstring str = (jstring)env->GetObjectArrayElement(strArr, i); //拿到对象数组的元素:注意要强制转换env->SetObjectArrayElement(newStr, i, str); //修改对象数组中的数据 }LOGD("修改后再看一遍3");for (int i = 0; i < len; ++i) {jstring str = (jstring)env->GetObjectArrayElement(newStr, i);const char *cstr = env->GetStringUTFChars(str, &isCopy);LOGD("字符串%d为:%s",i,cstr);env->ReleaseStringUTFChars(str, cstr);}}
结果:
######对象类型数组测试######### D/Canopencommand: 字符串0为:haha D/Canopencommand: 字符串1为:hehe D/Canopencommand: 字符串2为:wawa D/Canopencommand: 字符串3为:dada D/Canopencommand: 修改后再看一遍2 D/Canopencommand: 字符串0为:abcdefg D/Canopencommand: 字符串1为:hehe D/Canopencommand: 字符串2为:wawa D/Canopencommand: 字符串3为:dada D/Canopencommand: 修改后再看一遍3 D/Canopencommand: 字符串0为:abcdefg D/Canopencommand: 字符串1为:hehe D/Canopencommand: 字符串2为:wawa
4. 在JNI中调用实例化对象中的方法1:(使用自身对象,自身已被实例化)
JAVA层:测试对象
public class CANopen {private static final String TAG = "CANopen";static {Log.d(TAG, "static1");System.loadLibrary("Canopen-lib");Log.d(TAG, "static2");}public native void testCallMethod();private void JNIcallback(){Log.d(TAG, "这是JNI从C/C++回调JAVA实例化对象中的方法");}private int JNIcallback2(int a, byte b){Log.d(TAG, "整型="+a+";字节="+b);return 3;}private String JNIcallback3(int a, String b, byte[]c){Log.d(TAG, "整型="+a);Log.d(TAG,"字符串="+b);Log.d(TAG,"数组长度="+c.length);return new String("hello world");} }
JAVA层:
Log.d(TAG, "onCreate1"); caNopen.testCallMethod(); Log.d(TAG, "onCreate2");
JNI层:
JNIEXPORT void JNICALL Java_com_aplex_canopen_CANopen_testCallMethod(JNIEnv *env, jobject obj){jboolean isCopy;//1. 先调用一个比较简单的(无参无返回)LOGD("##########第一个############");jclass jc = env->GetObjectClass(obj); //通过实例化对象找到类jmethodID id = env->GetMethodID(jc, "JNIcallback", "()V"); //找到实例化对象里函数的IDenv->CallVoidMethod(obj, id); //调用obj这个实例化对象里的函数id//2. 调用稍微复杂点的(基本类型参数和返回值)LOGD("##########第二个############");jclass jc2 = env->GetObjectClass(obj); //通过实例化对象找到类jmethodID id2 = env->GetMethodID(jc2, "JNIcallback2", "(IB)I"); //找到实例化对象里函数的IDjint i = env->CallIntMethod(obj, id2, 0x1234, 5); //调用obj这个实例化对象里的函数idLOGD("JNI中返回参数=%d",i);//3. 调用一个比较复杂的(带对象类型参数和返回值)LOGD("##########第三个############");jclass jc3 = env->GetObjectClass(obj); //通过实例化对象找到类jmethodID id3 = env->GetMethodID(jc3, "JNIcallback3", "(ILjava/lang/String;[B)Ljava/lang/String;"); //找到实例化对象里函数的ID//创建byte数组,注意:无法赋值!!!jbyteArray byteArray = env->NewByteArray(45);int len = env->GetArrayLength(byteArray);//创建一个string并赋值jstring jstr = env->NewStringUTF("fuck!!");jstring str = (jstring)env->CallObjectMethod(obj, id3, 12, jstr,byteArray); //调用obj2这个实例化对象里的函数id,返回值是对象,要进行强制转换const char* cstr = env->GetStringUTFChars(str,&isCopy);LOGD("JNI中打印:%s", cstr);env->ReleaseStringUTFChars(str, cstr);}
结果:
D/MainActivity: onCreate1D/Canopencommand: ##########第一个############D/CANopen: 这是JNI从C/C++回调JAVA实例化对象中的方法D/Canopencommand: ##########第二个############D/CANopen: 整型=4660;字节=5D/Canopencommand: JNI中返回参数=3D/Canopencommand: ##########第三个############D/CANopen: 整型=12D/CANopen: 字符串=fuck!!D/CANopen: 数组长度=45D/Canopencommand: JNI中打印:hello worldD/MainActivity: onCreate2
5. 在JNI中调用实例化对象中的方法2:(新建实例化对象,修改对象的属性值,调用对象方法)
需要实例化的对象:
package com.aplex.canopen;import android.util.Log;public class TestClass {private String TAG = "TestClass";private int a;TestClass(){a = 1;Log.d(TAG,"调用无参构造函数");}TestClass(int a){this.a = a;Log.d(TAG,"调用有参构造函数="+a);}public int getValue(){Log.d(TAG, "a="+this.a);return this.a;} }
JAVA层:
Log.d(TAG, "onCreate1"); caNopen.testCallMethod2(); Log.d(TAG, "onCreate2");
JNI层:
JNIEXPORT void JNICALL Java_com_aplex_canopen_CANopen_testCallMethod2(JNIEnv *env, jobject obj){//1. 调用无参构造函数、修改变量(属性)值LOGD("##########调用无参构造函数############");jclass jc = env->FindClass("com/aplex/canopen/TestClass"); //找到类,该类未被实例化jmethodID initID = env->GetMethodID(jc, "<init>", "()V");//找到构造函数的id;注意:构造函数"<init>"为固定值jobject mobj = env->NewObject(jc, initID); //实例化一个对象 jmethodID funcID = env->GetMethodID(jc, "getValue", "()I"); //拿到方法的IDjint i = env->CallIntMethod(mobj, funcID); //调用方法LOGD("修改前查看函数返回的a=%d",i);jfieldID fieldID = env->GetFieldID(jc, "a", "I"); //拿到变量(属性)的IDjint ii = env->GetIntField(mobj, fieldID);LOGD("查看拿到的值a=%d",ii);ii = 100;env->SetIntField(mobj, fieldID, ii);jint iii = env->CallIntMethod(mobj, funcID); //再次调用查看是否修改属性值LOGD("修改后查看函数返回的a=%d",iii);//2. 调用有参构造函数LOGD("##########调用有参构造函数############");jclass jc2 = env->FindClass("com/aplex/canopen/TestClass");jmethodID initID2 = env->GetMethodID(jc2, "<init>", "(I)V"); //注意这里:"(I)V"jobject mobj2 = env->NewObject(jc2, initID2, 123);jmethodID funcID2 = env->GetMethodID(jc2, "getValue", "()I");jint i2 = env->CallIntMethod(mobj2, funcID2);LOGD("a=%d",i2); }
结果:
D/MainActivity: onCreate1D/Canopencommand: ##########调用无参构造函数############D/TestClass: 调用无参构造函数D/TestClass: a=1D/Canopencommand: 修改前查看函数返回的a=1D/Canopencommand: 查看拿到的值a=1D/TestClass: a=100D/Canopencommand: 修改后查看函数返回的a=100D/Canopencommand: ##########调用有参构造函数############D/TestClass: 调用有参构造函数=123D/TestClass: a=123D/Canopencommand: a=123D/MainActivity: onCreate2
6. 异常处理
JAVA层:
caNopen.testException();
JNI层:
JNIEXPORT void JNICALL Java_com_aplex_canopen_CANopen_testException(JNIEnv *env, jobject obj){jclass jc = env->FindClass("java/io/IOException");env->ThrowNew(jc, "异常测试");}
结果:
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.aplex.canopen, PID: 20296 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.aplex.canopen/com.aplex.canopen.MainActivity}: java.io.IOException: 异常测试 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) at android.app.ActivityThread.-wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5422) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: java.io.IOException: 异常测试 at com.aplex.canopen.CANopen.testException(Native Method) at com.aplex.canopen.MainActivity.onCreate(MainActivity.java:46) at android.app.Activity.performCreate(Activity.java:6251) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) at android.app.ActivityThread.-wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5422) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
转载于:https://www.cnblogs.com/maogefff/p/8386768.html
(三)JNI常用示例相关推荐
- Android JNI(三)——JNI数据结构之JNINativeMethod
上俩篇,我们讲了都是jni基础的原理知识以及如何使用cmake实现简单的jni.接下来本想讲解Java与Native相互调用的,但是发现Java与Native相互调用中设计了好多基础知识,其中用的比较 ...
- 《Python数据分析基础教程:NumPy学习指南(第2版)》笔记5:第三章 常用函数1——文件读写、算术平均值、最大值最小值、极值
本章将介绍NumPy的常用函数.具体来说,我们将以分析历史股价为例,介绍怎样从文件中载入数据,以及怎样使用NumPy的基本数学和统计分析函数.这里还将学习读写文件的方法,并尝试函数式编程和NumPy线 ...
- 《Python数据分析基础教程:NumPy学习指南(第2版)》笔记8:第三章 常用函数4——线性模型、数组修剪与压缩、阶乘
本章将介绍NumPy的常用函数.具体来说,我们将以分析历史股价为例,介绍怎样从文件中载入数据,以及怎样使用NumPy的基本数学和统计分析函数.这里还将学习读写文件的方法,并尝试函数式编程和NumPy线 ...
- SpringBoot之ElasticsearchRestTemplate常用示例
目录 1.引入pom依赖 2.application 配置 3.JavaBean配置以及ES相关注解 3.1 Student实体类 3.2 Teacher实体类 3.3 Headmaster 实体类 ...
- 朴素贝叶斯的三个常用模型: 高斯、多项、伯努利的原理和解释
在学习用朴素贝叶斯模型做文本分类的时候, 发现朴素贝叶斯是基于三个常用的模型, 高斯, 多项式, 和伯努利,所以查资料发现了一篇比较好的博客解释着三个模型的原理和区别. 所以转载一下: 原文出处:ht ...
- 三款常用接收机架构之间的PK
三款常用接收机架构之间的PK 今天比较三种常用接收机架构的优势和挑战-- 外差接收机 直接采样接收机 直接变频接收机 我们的意图并非要褒扬某种方案而贬抑其他方案,相反,本文旨在说明这些方案的优点和缺点 ...
- 《Python数据分析基础教程:NumPy学习指南(第2版)》笔记6:第三章 常用函数2——中位数、方差、日期、展平
本章将介绍NumPy的常用函数.具体来说,我们将以分析历史股价为例,介绍怎样从文件中载入数据,以及怎样使用NumPy的基本数学和统计分析函数.这里还将学习读写文件的方法,并尝试函数式编程和NumPy线 ...
- c语言如何持续输入字符直到指定字符结束_《小白学C》第三章 常用输入输出函数...
第三章 常用输入/输出函数 与其他高级语言一样, C语言的语句是用来向计算机系统发出操作指令的. 当我们提到输入时,这意味着要向程序填充一些数据.输入可以是以文件的形式或从命令行中进行.C 语言提供了 ...
- 中 找多个平面_数学一轮复习30,平面向量的概念及线性运算,三个常用结论
[考试要求] 1.了解向量的实际背景: 2.理解平面向量的意义和两个向量相等的含义: 3.理解向量的几何表示和基本要素: 4.掌握向量加法.减法的运算,并理解其几何意义: 5.掌握向量数乘的运算及其几 ...
最新文章
- linux uvc 支持的设备,摄像头是否支持uvc
- WPF 快速制作可拖拽的对象和窗体
- UDLD(Unidirectional Link Detection)
- php如何提高程序运行效率,如何提高PHP的运行效率 | 萧小寒
- easyui的datagrid的使用方法
- 洛阳计算机学校排名2015年,洛阳最好的中专学校有哪些 十大中专学校排名
- seafile Windows MySQL_seafile4.3.1 + windows 2012 server +mysql 部署记录(3)
- 数据分析师的30种死法
- springboot + mybatis-plus + quaryz 数据库持久化任务调度
- 内点法解不等式约束的优化问题
- c#语言猜数字游戏,C#实现简易猜数字游戏
- java通过调用鼠标模拟自动添加微信好友
- 企业微信自动打卡插件开发
- 基于宜搭的《T恤尺码收集》应用搭建
- linux中24点游戏下载,怀旧24点官网版-怀旧24点游戏下载v2.0.0-Linux公社
- 成为一名大数据工程师,需要具备什么技能?
- 搬家网企业如何网络营销,做好网络营销推广
- 数学二英语一计算机学校,研究生招生考试中英语一和英语二,数学一、数学二和数学三有什么区别、侧重点?听说英语一比英语二简单,数学一是计算机类专业考的等等,是这样的情况吗?...
- 黑莓9900应用收集
- Temporal Shift Module(TSM) 部署在自己电脑上并训练自己的数据集
热门文章
- 神舟战神win10改linux,神州战神G40把win10改成win7的详细教程(包括BIOS设置图)
- java在进行流操作的close()方法
- Python处理excel基本操作
- (求老师啊,求同伴啊)php 生命数字密码设计第一步:数据库基本连接
- 分布式一致性协议三部曲-从paxos幽灵复现看Raft实现原理
- HTML5新标签-结构标签、表单元素、媒体标签
- 三相三线STATCOM仿真模型。无功电流采用ipiq检测,pwm采用滞环控制。
- 商城搜索DSL elasticsearch 相关代码
- 大头贴制作大师 6.9.5 下载
- Python脚本批量重命名图片