(原)android的JNI中使用C++的类
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++的类的更多相关文章
- [Android Pro] Android studio jni中调用Log输出调试信息
reference to : http://www.linuxidc.com/Linux/2014-02/96341.htm Android 开发中,java 可以方便的使用调试信息Log.i, Lo ...
- (原)android的alertdialog中加入edittext但是不弹出软键盘等问题的解决与原因
摘要:alertdialog中加入edittext但是不弹出软键盘等问题网上有很多不管用的解决方案, 本文意在给出更有效的解决办法,并初步探究其原因 正文 在对话框中插入文本框是十分常见的需求 通常我 ...
- (原+转)Eclipse中Android调用OpenCv
大部分都是参考下面的网址,如果感觉看起来不舒服,可以直接查看原网址.最后遇到了一点问题: Description Resource Path Location Type E:/~\cod ...
- android的JNI 、 NDK 学习!
转载的! Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) ...
- android的JNI标准 android的NDK
转载的! Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) ...
- [原] Android 自定义View步骤
例子如下:Android 自定义View 密码框 例子 1 良好的自定义View 易用,标准,开放. 一个设计良好的自定义view和其他设计良好的类很像.封装了某个具有易用性接口的功能组合,这些功能能 ...
- 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 ...
- Base64编解码Android和ios的例子,补充JNI中的例子
1.在Android中java层提供了工具类:android.util.Base64; 里面都是静态方法,方便直接使用: 使用方法如下: // Base64 编码: byte [] encode = ...
- android学习笔记----JNI中的c控制java
面向对象的底层实现 java作为面向对象高级语言,可对现实世界进行建模.和面向过程不同的是面向对象软件的编写不是流程的堆积,而是对业务逻辑的多视角分解和分类.其过程大致为: 1).将知识分解 ...
随机推荐
- 关于DCLP实现的单例模式的一些想法
关于DCLP实现的单例模式的一些想法 我之前写过单例的文章( http://www.cnblogs.com/mkdym/p/4908644.html ),但是现在又有了一些想法,不想再在原来那篇文章上 ...
- 迁移google code上的项目到本地版本库
今年五月份以来就已经连接不上google code了,翻*墙又极度不稳定,在忍受了几个月之后终于决定将项目搬离google code;经过研究之后终于实现了搬迁到本地,最后总结成下文.一者期望对有需要 ...
- MySQL 常用字段类型,介绍及其建表使用方法经验分享
由于工作的公司没有专业的DBA又经常需要建立各种各种的表来满足自己的业务逻辑,所以经常查看MySQL 手册或者谷歌查看相关资料,所以本人就根据我的工作经验和相关资料来介绍一下MySQL各种字段类型及其 ...
- iOS开发之OC篇-响应式编程Reactive Cocoa
一.Reactive Cocoa 介绍 Reactive Cocoa 是 iOS 开发的一个 "重量级" 框架 高大上的概念:响应式编程 核心概念:信号 Signal 官方网站:h ...
- linux下源码安装apache服务
1.搭建静态网站是,我们只需要搭建apache服务即可满足要求. 例如:如果我再客户端游览器输入地址,他会找到192.168.1.100这个服务器,然后根据端口会找到apache服务器.apache他 ...
- Windows7里的“计算器”你真的会用吗?
“计算器”是不同Windows版本中的必备工具,虽然功能单一,但的确是人们日常工作中不可缺少的辅助工具,本文就来谈谈它的使用. 一.标准型和科学型两种面板 我们既可从Windows附件菜单中启动它,也 ...
- UltraEdit的语法高亮显示配置
今天吴同学看到我电脑中有UltraEdit好奇地问我会不会用,我那个汗啊,不会用我装它干什么啊?其实当时装UltraEdit主要是用来写Java的,没有想到,工作一忙顾及不上学习Java的事情了.于是 ...
- LINQ to SQL和Entity Framework对比与关联 (转载)
LINQ to SQL和Entity Framework对比与关联 LINQ to SQL和Entity Framework都是一种包含LINQ功能的对象关系映射技术.他们之间的本质区别在 ...
- shell重定向
输入重定向 和输出重定向一样,Unix 命令也可以从文件获取输入,语法为: command < file 这样,本来需要从键盘获取输入的命令会转移到文件读取内容. 注意:输出重定向是大于号(&g ...
- mongodb数据库备份恢复
MongoDB数据文件备份与恢复 备份与恢复数据对于管理任何数据存储系统来说都是非常重要的. 1.冷备份与恢复——创建数据文件的副本(前提是要停止MongoDB服务器),也就是直接copy ...