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

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

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

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

c求和函数calcSum

d求平均值函数calcMean

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

 // myMeanSum.h文件
#pragma once #include <stdio.h>
#include <stdlib.h> class myMeanSum
{
public:
myMeanSum();
~myMeanSum();
myMeanSum(int* data, int num); double calcMean();
int calcSum(); private:
int m_number;
int* databuf;
double m_mean;
int m_sum;
};
 // myMeanSum.cpp文件

 #include "myMeanSum.h"

 myMeanSum::myMeanSum()
: m_mean()
, m_sum()
, m_number()
{
databuf = new int[];
} myMeanSum::myMeanSum(int* data, int num)
: m_mean()
, m_sum()
, m_number()
{
m_number = num;
databuf = new int[m_number];
memcpy(databuf, data, sizeof(int)*m_number);
} myMeanSum::~myMeanSum()
{
if (databuf!=NULL)
{
delete[] databuf;
databuf = NULL;
}
} double myMeanSum::calcMean()
{
m_sum = calcSum();
return m_sum / 1.0 / m_number; // / 1.0用来保证int类型自动转换成double类型。
} int myMeanSum::calcSum()
{
m_sum = ;
for (int i = ; i < m_number; i++)
{
m_sum += databuf[i];
}
return m_sum;
}

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

3. 添加JNI文件AndroidClass.cpp。

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

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

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

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

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

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

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

 JNIEXPORT jlong JNICALL Java_com_example_testclass_AndroidClass_AndroidClassGen
(JNIEnv *env, jobject obj, jintArray data, jint num)
{
jint *iAdata = env->GetIntArrayElements(data, ); jlong ptr= reinterpret_cast<jlong>(new myMeanSum(reinterpret_cast<int*>(iAdata), num)); env->ReleaseIntArrayElements(data, iAdata, ); return ptr;
}

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

 public void AndroidClassFree()
{
AndroidClassFree(ptr_);
}
private native void AndroidClassFree(long ptr);

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

 JNIEXPORT void JNICALL Java_com_example_testclass_AndroidClass_AndroidClassFree
(JNIEnv *, jobject, jlong ptr)
{
if(reinterpret_cast<myMeanSum*>(ptr))
{
delete reinterpret_cast<myMeanSum*>(ptr);
ptr = ;
}
}

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中添加如下简单的测试代码:

 int number = ;
int* data = new int[number];
for (int i = ; i < number; i++)
{
data[i] = i;
}
myMeanSum temp(data, number);
printf("%d\n", temp.calcSum());
printf("%f\n", temp.calcMean());

输出为

4.500000

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

 int number = ;
int[] data = new int[number];
for (int i = ; i < number; i++)
{
data[i] = i;
} AndroidClass test=new AndroidClass(data,number);
System.out.println("test-----"+test.calcSum());
System.out.println("test-----"+test.calcMean());
test.AndroidClassFree();

结果如下:

证明程序正确。

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

  int number = *;
int[] data = new int[number];
for (int i = ; i < number; i++)
{
data[i] = i;
} for(int i=;i<;i++)
{
AndroidClass test=new AndroidClass(data,number);
System.out.println("test-----"+i+" "+test.calcSum());
System.out.println("test-----"+i+" "+test.calcMean());
test.AndroidClassFree();
}

程序执行完没有出错。证明析构函数能正确的执行,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 Pro] Android studio jni中调用Log输出调试信息

    reference to : http://www.linuxidc.com/Linux/2014-02/96341.htm Android 开发中,java 可以方便的使用调试信息Log.i, Lo ...

  2. (原)android的alertdialog中加入edittext但是不弹出软键盘等问题的解决与原因

    摘要:alertdialog中加入edittext但是不弹出软键盘等问题网上有很多不管用的解决方案, 本文意在给出更有效的解决办法,并初步探究其原因 正文 在对话框中插入文本框是十分常见的需求 通常我 ...

  3. (原+转)Eclipse中Android调用OpenCv

    大部分都是参考下面的网址,如果感觉看起来不舒服,可以直接查看原网址.最后遇到了一点问题: Description      Resource Path Location   Type E:/~\cod ...

  4. android的JNI 、 NDK 学习!

    转载的! Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) ...

  5. android的JNI标准 android的NDK

    转载的! Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) ...

  6. [原] Android 自定义View步骤

    例子如下:Android 自定义View 密码框 例子 1 良好的自定义View 易用,标准,开放. 一个设计良好的自定义view和其他设计良好的类很像.封装了某个具有易用性接口的功能组合,这些功能能 ...

  7. ZT ANDROID jni 中的事件回调机制JNIenv的使用 2012-09-10 12:53:01

    ANDROID jni 中的事件回调机制JNIenv的使用 2012-09-10 12:53:01 分类: 嵌入式 android framework 里java调用native,使用JNI机制,ja ...

  8. Base64编解码Android和ios的例子,补充JNI中的例子

    1.在Android中java层提供了工具类:android.util.Base64; 里面都是静态方法,方便直接使用: 使用方法如下: // Base64 编码: byte [] encode =  ...

  9. android学习笔记----JNI中的c控制java

    面向对象的底层实现 java作为面向对象高级语言,可对现实世界进行建模.和面向过程不同的是面向对象软件的编写不是流程的堆积,而是对业务逻辑的多视角分解和分类.其过程大致为:      1).将知识分解 ...

随机推荐

  1. 通过AJAX和PHP,提交JQuery Mobile表单

    File name: callajax.php <?php $firstName = $_POST[firstName]; $lastName = $_POST[lastName]; echo( ...

  2. ORACLE11G常用函数

    1 单值函数 1.1 日期函数 1.1.1 Round [舍入到最接近的日期](day:舍入到最接近的星期日) select sysdate S1, round(sysdate) S2 , round ...

  3. 在Python3.5下安装和测试Scrapy爬网站

    1. 引言 Scrapy框架结构清晰,基于twisted的异步架构可以充分利用计算机资源,是爬虫做大的必备基础.本文将讲解如何快速安装此框架并使用起来. 2. 安装Twisted 2.1 同安装Lxm ...

  4. zabbix之3触发器/action及模板

    1.触发器: {server_name:item_name.func.operator.condition} 一旦condition(条件)触发,则item状态改变 触发器之间可以存在依赖关系,即it ...

  5. Stall Reservations(POJ 3190 贪心+优先队列)

    Stall Reservations Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4434   Accepted: 158 ...

  6. Android中SensorManager.getRotationMatrix函数原理解释

    SensorManager是Android中的一个类,其有一个函数getRotationMatrix,可以计算出旋转矩阵,进而通过getOrientation求得设备的方向(航向角.俯仰角.横滚角). ...

  7. 挑战以Dropbox为代表的传统“同步网盘”,Seafile推出“分布式文件同步技术”打造的私有云服务

    挑战以Dropbox为代表的传统“同步网盘”,Seafile推出“分布式文件同步技术”打造的私有云服务#36氪开放日# 其他 JasonZheng • 2012-04-07 15:14 来自36氪开放 ...

  8. ArcGis API FOR Silverlight 做了个导航工具~

    原文 http://www.cnblogs.com/thinkaspx/archive/2012/08/08/2628214.html 转载请注明文章出处:http://www.cnblogs.com ...

  9. python刷取CSDN博文访问量之一

    python刷取CSDN博文访问量之一 作者:vpoet 注:这个系列我只贴代码,代码不注释.有兴趣的自己读读就懂了,纯属娱乐,望管理员抬手 若有转载一定不要注明来源   #coding=utf-8 ...

  10. C#执行zip文件压缩的几种方法及我遇到的坑总结

    工作项目中需要用到zip压缩解压缩文件,一开始看上了Ionic.Zip.dll这个类库,操作方便,写法简单 对应有个ziphelper类 using Ionic.Zip; public static ...