(原)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).将知识分解 ...
随机推荐
- samba搭建
在局域网下 samba可以代替ftp 用于传输 可以更高效的并行开发 安装samba sudo apt-get install samba samba-common 创建要共享的文件夹 mkdir / ...
- python 技巧 之 pyCharm快速添加第三方库和插件
学习python有几个月,安装第三方库都是通过 pip install 或者 easy_install.每次都要打开命令行感觉太麻烦.还好Pycharm提供了安装第三方库和安装插件的功能. 首先打开P ...
- C++服务器设计(四):超时管理机制设计
前四章介绍了系统层的设计,从这一章开始进入服务层的设计. 连接断开 在常见的服务器场景中,客户端断开连接的方式为被动关闭.即作为客户端请求完服务器的服务后,选择主动关闭同服务器的连接.在服务器的角度看 ...
- Mysql MERGE 引擎在分表环境下得使用
应用场景:当我们在做分表的时候,通常会把一个大表的数据拆分成若干个分表,这也是数据库优化中的分表概念.随着分表随之而来的问题就是多表查询. 现在有 t1,t2 两张数据表,需要满足不同的查询条件同时从 ...
- c# 大数据量比较时-方案
1.当面临千万条数据量的比较时,从技术的角度来说应该用泛型键值(c#键值由于用了散列算法速度很快).例如前几天我需要查的是 航空公司.出发.到达.返点可以将 航空公司-出发-到达做一个键,返点作为值. ...
- ubuntu 中c 语言编程(学习)
ubuntu下c编程 c编程中相关文件后缀 .a 静态库(archive .c C源代码(需要编译预处理) .h C源代码头文件 .i C源代码 (不需要编译预处理) ...
- poj 1129 Channel Allocation
http://poj.org/problem?id=1129 import java.util.*; import java.math.*; public class Main { public st ...
- Delphi线程同步(临界区、互斥、信号量,包括详细代码)
当有多个线程的时候,经常需要去同步这些线程以访问同一个数据或资源. 例如,假设有一个程序,其中一个线程用于把文件读到内存,而另一个线程用于统计文件的字符数.当然,在整个文件调入内存之前,统计它的计数是 ...
- jQuery 获取 URL信息
jQuery获取URL信息有很多方法,但是使用这个插件就非常爽了. 托管地址在:http://github.com/allmarkedup/jQuery-URL-Parser // http: //l ...
- C语言调用库函数实现生产者消费者问题
#include<stdio.h> #include<stdlib.h> #include<semaphore.h> #include<pthread.h&g ...