针对我之前文章的练习: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常用示例相关推荐

  1. Android JNI(三)——JNI数据结构之JNINativeMethod

    上俩篇,我们讲了都是jni基础的原理知识以及如何使用cmake实现简单的jni.接下来本想讲解Java与Native相互调用的,但是发现Java与Native相互调用中设计了好多基础知识,其中用的比较 ...

  2. 《Python数据分析基础教程:NumPy学习指南(第2版)》笔记5:第三章 常用函数1——文件读写、算术平均值、最大值最小值、极值

    本章将介绍NumPy的常用函数.具体来说,我们将以分析历史股价为例,介绍怎样从文件中载入数据,以及怎样使用NumPy的基本数学和统计分析函数.这里还将学习读写文件的方法,并尝试函数式编程和NumPy线 ...

  3. 《Python数据分析基础教程:NumPy学习指南(第2版)》笔记8:第三章 常用函数4——线性模型、数组修剪与压缩、阶乘

    本章将介绍NumPy的常用函数.具体来说,我们将以分析历史股价为例,介绍怎样从文件中载入数据,以及怎样使用NumPy的基本数学和统计分析函数.这里还将学习读写文件的方法,并尝试函数式编程和NumPy线 ...

  4. SpringBoot之ElasticsearchRestTemplate常用示例

    目录 1.引入pom依赖 2.application 配置 3.JavaBean配置以及ES相关注解 3.1 Student实体类 3.2 Teacher实体类 3.3 Headmaster 实体类 ...

  5. 朴素贝叶斯的三个常用模型: 高斯、多项、伯努利的原理和解释

    在学习用朴素贝叶斯模型做文本分类的时候, 发现朴素贝叶斯是基于三个常用的模型, 高斯, 多项式, 和伯努利,所以查资料发现了一篇比较好的博客解释着三个模型的原理和区别. 所以转载一下: 原文出处:ht ...

  6. 三款常用接收机架构之间的PK

    三款常用接收机架构之间的PK 今天比较三种常用接收机架构的优势和挑战-- 外差接收机 直接采样接收机 直接变频接收机 我们的意图并非要褒扬某种方案而贬抑其他方案,相反,本文旨在说明这些方案的优点和缺点 ...

  7. 《Python数据分析基础教程:NumPy学习指南(第2版)》笔记6:第三章 常用函数2——中位数、方差、日期、展平

    本章将介绍NumPy的常用函数.具体来说,我们将以分析历史股价为例,介绍怎样从文件中载入数据,以及怎样使用NumPy的基本数学和统计分析函数.这里还将学习读写文件的方法,并尝试函数式编程和NumPy线 ...

  8. c语言如何持续输入字符直到指定字符结束_《小白学C》第三章 常用输入输出函数...

    第三章 常用输入/输出函数 与其他高级语言一样, C语言的语句是用来向计算机系统发出操作指令的. 当我们提到输入时,这意味着要向程序填充一些数据.输入可以是以文件的形式或从命令行中进行.C 语言提供了 ...

  9. 中 找多个平面_数学一轮复习30,平面向量的概念及线性运算,三个常用结论

    [考试要求] 1.了解向量的实际背景: 2.理解平面向量的意义和两个向量相等的含义: 3.理解向量的几何表示和基本要素: 4.掌握向量加法.减法的运算,并理解其几何意义: 5.掌握向量数乘的运算及其几 ...

最新文章

  1. linux uvc 支持的设备,摄像头是否支持uvc
  2. WPF 快速制作可拖拽的对象和窗体
  3. UDLD(Unidirectional Link Detection)
  4. php如何提高程序运行效率,如何提高PHP的运行效率 | 萧小寒
  5. easyui的datagrid的使用方法
  6. 洛阳计算机学校排名2015年,洛阳最好的中专学校有哪些 十大中专学校排名
  7. seafile Windows MySQL_seafile4.3.1 + windows 2012 server +mysql 部署记录(3)
  8. 数据分析师的30种死法
  9. springboot + mybatis-plus + quaryz 数据库持久化任务调度
  10. 内点法解不等式约束的优化问题
  11. c#语言猜数字游戏,C#实现简易猜数字游戏
  12. java通过调用鼠标模拟自动添加微信好友
  13. 企业微信自动打卡插件开发
  14. 基于宜搭的《T恤尺码收集》应用搭建
  15. linux中24点游戏下载,怀旧24点官网版-怀旧24点游戏下载v2.0.0-Linux公社
  16. 成为一名大数据工程师,需要具备什么技能?
  17. 搬家网企业如何网络营销,做好网络营销推广
  18. 数学二英语一计算机学校,研究生招生考试中英语一和英语二,数学一、数学二和数学三有什么区别、侧重点?听说英语一比英语二简单,数学一是计算机类专业考的等等,是这样的情况吗?...
  19. 黑莓9900应用收集
  20. Temporal Shift Module(TSM) 部署在自己电脑上并训练自己的数据集

热门文章

  1. 神舟战神win10改linux,神州战神G40把win10改成win7的详细教程(包括BIOS设置图)
  2. java在进行流操作的close()方法
  3. Python处理excel基本操作
  4. (求老师啊,求同伴啊)php 生命数字密码设计第一步:数据库基本连接
  5. 分布式一致性协议三部曲-从paxos幽灵复现看Raft实现原理
  6. HTML5新标签-结构标签、表单元素、媒体标签
  7. 三相三线STATCOM仿真模型。无功电流采用ipiq检测,pwm采用滞环控制。
  8. 商城搜索DSL elasticsearch 相关代码
  9. 大头贴制作大师 6.9.5 下载
  10. Python脚本批量重命名图片