android的JNI代码中可以调用C++的类,但是不能直接调用,要加上一个类似于接口的java类,这个类内部调用C++的类。实际上和接口类直接调用C++中的函数差不多,只是稍微复杂了一点。

1. 写一个简单的类(一直都是用VS自动生成的类,很少自己写一个类,因而此处也是用VS生成类,然后复制到Eclipse工程的jni目录下。)该类包含4个函数:

a带参数的构造函数,用于初始化类中的变量。

b析构函数,用于释放类中的指针(数组)

c求和函数calcSum

d求平均值函数calcMean

下面的代码是VS转到JNI后编译通过的代码(VS生成的可能需要稍微修改一点)

 1 // myMeanSum.h文件
 2 #pragma once
 3
 4 #include <stdio.h>
 5 #include <stdlib.h>
 6
 7 class myMeanSum
 8 {
 9 public:
10     myMeanSum();
11     ~myMeanSum();
12     myMeanSum(int* data, int num);
13
14     double calcMean();
15     int calcSum();
16
17 private:
18     int m_number;
19     int* databuf;
20     double m_mean;
21     int m_sum;
22 };

 1 // myMeanSum.cpp文件
 2
 3 #include "myMeanSum.h"
 4
 5 myMeanSum::myMeanSum()
 6 : m_mean(0)
 7 , m_sum(0)
 8 , m_number(0)
 9 {
10     databuf = new int[10];
11 }
12
13 myMeanSum::myMeanSum(int* data, int num)
14 : m_mean(0)
15 , m_sum(0)
16 , m_number(0)
17 {
18     m_number = num;
19     databuf = new int[m_number];
20     memcpy(databuf, data, sizeof(int)*m_number);
21 }
22
23
24 myMeanSum::~myMeanSum()
25 {
26     if (databuf!=NULL)
27     {
28         delete[] databuf;
29         databuf = NULL;
30     }
31 }
32
33
34 double myMeanSum::calcMean()
35 {
36     m_sum = calcSum();
37     return m_sum / 1.0 / m_number;  // / 1.0用来保证int类型自动转换成double类型。
38 }
39
40
41 int myMeanSum::calcSum()
42 {
43     m_sum = 0;
44     for (int i = 0; i < m_number; i++)
45     {
46         m_sum += databuf[i];
47     }
48     return m_sum;
49 }

2. 在Eclipse中创建新的android工程testClass。

3. 添加JNI文件AndroidClass.cpp。

4. 添加接口文件AndroidClass.java。

5. 在AndroidClass.java中添加long类型的指针,用于存储类的地址private long ptr_;

6. 在AndroidClass.java添加AndroidClass的构造函数:

1 public AndroidClass(int[] data, int num)
2 {
3     ptr_=AndroidClassGen(data, num);
4 }

7. 在AndroidClass.java添加6中函数调用的函数接口:

private native long AndroidClassGen(int[] data, int num);

8. 在AndroidClass.cpp添加7中调用class的接口函数。

 1 JNIEXPORT jlong JNICALL Java_com_example_testclass_AndroidClass_AndroidClassGen
 2   (JNIEnv *env, jobject obj, jintArray data, jint num)
 3 {
 4     jint *iAdata = env->GetIntArrayElements(data, 0);
 5
 6     jlong ptr= reinterpret_cast<jlong>(new myMeanSum(reinterpret_cast<int*>(iAdata), num));
 7
 8     env->ReleaseIntArrayElements(data, iAdata, 0);
 9
10     return ptr;
11 }

9. 在AndroidClass.java添加释放内存的函数AndroidClassFree,感觉这两个函数名字不一定需要相同(相同没有错误,不相同没测试)。

1 public void AndroidClassFree()
2 {
3     AndroidClassFree(ptr_);
4 }

private native void AndroidClassFree(long ptr);

10. 在AndroidClass.cpp添加9中调用class的接口函数。

1 JNIEXPORT void JNICALL Java_com_example_testclass_AndroidClass_AndroidClassFree
2   (JNIEnv *, jobject, jlong ptr)
3 {
4     if(reinterpret_cast<myMeanSum*>(ptr))
5     {
6         delete reinterpret_cast<myMeanSum*>(ptr);
7         ptr = 0;
8     }
9 }

11. 在android.mk中添加需要编译的C++类的源文件(默认是LOCAL_SRC_FILES := AndroidClass.cpp):

LOCAL_SRC_FILES := AndroidClass.cpp myMeanSum.cpp

12. 分别添加其他的代码,此处略去,详见工程:

https://github.com/darkknightzh/testClass

说明:AndroidClassGetPtr程序不使用,如果需要在外部的AndroidClass定义的对象A使用对象B,则使用这个函数传入 B的指针。

测试步骤:

1. 在VS中添加如下简单的测试代码:

1 int number = 10;
2 int* data = new int[number];
3 for (int i = 0; i < number; i++)
4 {
5     data[i] = i;
6 }
7 myMeanSum temp(data, number);
8 printf("%d\n", temp.calcSum());
9 printf("%f\n", temp.calcMean());

输出为

45
4.500000

2. 在Eclipse的MainActivity.java的onCreate中添加如下测试代码:

 1 int number = 10;
 2 int[] data = new int[number];
 3 for (int i = 0; i < number; i++)
 4 {
 5       data[i] = i;
 6 }
 7
 8 AndroidClass test=new AndroidClass(data,number);
 9 System.out.println("test-----"+test.calcSum());
10 System.out.println("test-----"+test.calcMean());
11 test.AndroidClassFree();

结果如下:

证明程序正确。

3. 为了证明class中的析构函数正确被调用,databuf申请的内存能正常释放,填写如下测试代码:

 1  int number = 1000*1000;
 2 int[] data = new int[number];
 3 for (int i = 0; i < number; i++)
 4 {
 5         data[i] = i;
 6 }
 7
 8 for(int i=0;i<1000;i++)
 9 {
10      AndroidClass test=new AndroidClass(data,number);
11      System.out.println("test-----"+i+"   "+test.calcSum());
12      System.out.println("test-----"+i+"   "+test.calcMean());
13       test.AndroidClassFree();
14 }

程序执行完没有出错。证明析构函数能正确的执行,databuf申请的内存能正常释放。

4. 注释掉test.AndroidClassFree();后,程序跑到128次的时候崩溃,之后继续从0开始跑。证明AndroidClassFree函数正确的执行了析构函数。

5. 跑上面3的代码,但是myMeanSum类中的析构函数里面的代码全部注释掉,程序跑到128次后依旧崩溃,证明AndroidClassFree函数正确的执行了析构函数。

ps,上面程序只是一个简单的例子,可能有不完善的地方,同时代码写得也不是很好。

参考网址(貌似不能愉快的访问,感谢原作者,以及不能愉快的访问的搜索引擎):

http://stylishtoupee.blogspot.jp/2011/07/jni-example-with-class-instantiation-c.html

(原)android的JNI中使用C++的类相关推荐

  1. 【Android】JNI调用(完整版)

    原文出处:http://blog.csdn.net/kangyaping/article/details/6584027#t0 Chap1:JNI完全手册... 3 Chap2:JNI-百度百科... ...

  2. Android与JNI(一)

    2019独角兽企业重金招聘Python工程师标准>>> Eddy_He 博客园 首页 新随笔 联系 订阅 管理 随笔- 55  文章- 0  评论- 3 Android与JNI(一) ...

  3. android 源码中的单例,Android源码中的一种单例实现

    单例模式的实现方式有懒汉,饿汉,双重校验锁,枚举,内部类等等,写法就不全部列举了.Android源码中有一个单例辅助类/frameworks/base/core/java/android/util/S ...

  4. android studio 自动提示jni代码,如何将JNI(C/C++本机代码)添加到现有的Android Studio项目中...

    从现有项目中执行以下步骤: 1.修改build.gradle(模块应用程序)看起来像这样(很多变化!): apply plugin: 'com.android.model.application' m ...

  5. 【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( jni 中 main 函数声明 | 命令行处理 | jni 调用 lib7zr.so 函数库处理压缩文件完整代码 )

    文章目录 一.JNI 中 main 函数声明 二.命令字符串切割并传入 main 函数 三.完整代码示例 1.完整 jni 代码 2.完整 java 代码 3.执行结果 四.参考资料 前置博客 : [ ...

  6. android+jni+构造函数,在JNI中调用构造函数失败Android

    我想从我的JNI Android代码调用构造函数;但不知何故,它失败,以下例外.. 我相信我失去了一些非常小的东西;但我无法弄清楚......任何人都可以请指出?在JNI中调用构造函数失败Androi ...

  7. android studio 导入模块SDK 以及该模块中继承application的类与原工程继承application的类存在冲突 解决方法

    android studio 导入模块SDK 以及该模块中继承application的类与原工程继承application的类存在冲突 解决方法 导入某修改后的海康视频SDK(老师给的),并修改相关文 ...

  8. android jni 中实现 LOG 输出调试

    android jni 中实现 LOG 输出调试 在jni 文件夹下 android.mk文件中 添加 LOCAL_LDLIBS += -L$(SYSTEM)/usr/lib -llog 在jni中添 ...

  9. Android For JNI(二)——C语言中的数据类型,输出,输入函数以及操作内存地址,内存修改器

    Android For JNI(二)--C语言中的数据类型,输出,输入函数以及操作内存地址,内存修改器 当我们把Hello World写完之后,我们就可以迈入C的大门了,今天就来讲讲基本的一些数据类型 ...

最新文章

  1. 虚拟机+可信+云计算
  2. 009_JavaScript语句、表达式和代码块
  3. 数据结构和算法解:第九章 算法设计技巧
  4. linux网络配置、测试及故障诊断方法和工具三
  5. 鼠标控制方向java代码_java鼠标操控小程序
  6. dagger2记录篇
  7. R语言观察日志(part18)--.C和.Call
  8. 实时监听输入框值变化的完美方案:oninput onpropertychange
  9. @requestparam @param @pathvariable @requestbody的区别
  10. 深入浅出理解HOG特征---梯度方向直方图
  11. django class类即视图类添加装饰器的几种方法
  12. TURBOMAIL邮件服务器—挽救错误邮件
  13. 【转】Python之装饰器
  14. yuv420sp转jpg
  15. 使用安卓模拟器+Xposed+JustTrustMe+burp suite抓取app的https流量
  16. go,go语言编辑器安装,git安装,即vscode三个插件的安装
  17. 2017会考计算机知识点,【高考备考】2017高二化学会考知识点汇总高中化学会考知识点...
  18. 机器学习服务文本识别能力演进,大幅提升识别准确率
  19. 苏州大学 计算机网络,苏州大学计算机网络与通信期末考试卷-20210517192500.docx-原创力文档...
  20. 按Backspace键删除时,会出现^H

热门文章

  1. linux重要的目录之etc
  2. linux之realpath命令
  3. 在线等差数列项生成器
  4. Java线程安全策略
  5. 2017-09-16
  6. Linux下的超级终端minicom与XGCom
  7. PC端稳定性测试探索
  8. CentOS Mysql安装配置
  9. 【推荐算法】协同过滤算法——基于用户 Java实现
  10. 数据库 设计中的英文术语