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. POJ 1698 (二分图的多重匹配)

    转载:http://www.cppblog.com/MatoNo1/archive/2011/03/26/142766.aspx 我们知道在一个图中,每个点最多只能匹配一条边的情况,是二分图的最大匹配 ...

  2. (原)ubuntu上安装qt

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5652429.html 参考网址: http://doc.qt.io/qt-4.8/install-x1 ...

  3. HTTP协议入门知识

    HTTP超文本传输协议,是客户端浏览器和服务器通信的规范,是浏览器与服务器通信的协议,属于应用层的协议,web开发者了解HTTP协议非常重要.浏览器通过http协议请求服务器,完成请求服务器立刻关闭连 ...

  4. SQL基础-->层次化查询(START BY ... CONNECT BY PRIOR)[转]

    --====================================================== --SQL基础-->层次化查询(START BY ... CONNECT BY ...

  5. 简易的WPF MVVM模式开发

    Model层 public class Song { private string _artistName; private string _songTitle; public string Song ...

  6. 让PHP程序永远在后台运行

    PHP里有个函数很有用.这是在最近的开发中才逐渐用到的. int ignore_user_abort ( [bool setting] ) 这个函数的作用是指示服务器端在远程客户端关闭连接后是否继续执 ...

  7. Mysql SlowLog 工具 pt-query-diglist

    工具地址:http://www.percona.com/doc/percona-toolkit/ 安装依赖工具 yum install perl-Time-HiRes 编译安装 perl Makefi ...

  8. Win7/Win8 系统下安装Oracle 10g 提示“程序异常终止,发生未知错误”的解决方法

    我的Oracle 10g版本是10.2.0.1.0,(10.1同理)选择高级安装,提示“程序异常终止,发生未知错误”. 1.修改Oracle 10G\database\stage\prereq\db\ ...

  9. information_schema.column_privileges 学习

    mysql 的授权是分层次的 实例级 | 库级 | 表级 | 列级 而这些授权信息被保存在了mysql.user | mysql.db | mysql.tables_priv | mysql.colu ...

  10. 关于onclick中的event对象和element对象

    event.srcElement:引发事件的目标对象,常用于onclick事件. event.fromElement:引发事件的对象源,常用于onmouseout和onmouseover事件. eve ...