[Android]JNI动态注册Java函数教程

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">最近在做关于JNI的项目,跟大家分享一些经验。</span>

关于在C层静态注册Java层的Demo网上已经有相当多的说明了。

这里是一个学习静态注册的很好的例子http://cherishlc.iteye.com/blog/1756762

可以先学习JNI的基本知识再学习下面的知识。

但是既然Java和C只是一个互调的过程,那么只要让JVM知道函数的对应关系就可以了。

这样就可以不需要那么长的函数名,而且以后对函数进行修改只需要修改头文件就行了,比较易于扩展和阅读。

直接开始。

首先说几点需要注意的:

1.在我们编写的C层的cpp文件时,它的会有生命周期函数加载的过程(我是这样理解称呼的)。

jint JNI_OnLoad(JavaVM* vm, void* reserved) {
}
上面这个函数会在加载的开始调用,可以在这里方法体里进行Java函数的动态注册。


可以在这个函数内编写

registerNativeMethods(env,"包名+类名"){
int result = 0;
result = env->RegisterNatives(clazz, gMethods,sizeof(gMethods) / sizeof(gMethods[0]));
//这里对result结果做处理
}


其中gMethods是函数声明:

static JNINativeMethod gMethods[] =
		{{ "native_XX", "()I",(void*)XX },其他函数}

对其说明一下,第一个参数是Java类中native函数的声明,第二个参数是函数的签名,括号内是函数的形参,后面跟的字母是返回值,因为Java具有多态性,确定一个函数的方式是唯一的函数名+形参+返回值,而(void*)是指在C语言中函数存放的类型,一般使用(void*),XX是在C语言中实现的函数名。


这样就实现了动态注册。


最后说一下在Java中的自动类怎么和C语言中的结构体对应起来。


一般的需求是在C层传输给Java层一个类,很简单,使用Object.


直接给Demo

Java层:
private int native_get(Object object){};

C层
//动态注册方法,第一个表示Java层的函数名,第二个表示(参数)返回值,第三个表示C层函数
static JNINativeMethod jMethods[] ={"native_get","(Ljava/lang/Object;)Ljava/lang/Object;",get}

//在JNI_OnLoad()中调用该动态注册函数
result = env->RegisterNatives(clazz, jMethods,
			sizeof(jMethods) / sizeof(jMethods[0]));

//编写C函数
JNIEXPORT jobject JNICALL get(
		JNIEnv *env, jclass thiz, jobject obj) {

	jclass cls = env->FindClass(JAVA层需要得到的包名+类名);//如 com/csdn/Student
	jfieldID issue = env->GetFieldID(cls, 类的成员变量名, 类型);//得到类的成员变量

	env->SetObjectField(obj, issue, "赋值");//给成员变量复制

	return obj;//返回对象

最后就可以在Java层调用改native函数获取到填充了值的object对象。


需要注意的是,必须在Java层传入一个新对象,C层只是负责给该对象填充值。


下面是一些类型在Java与C的互换


以下搬运自http://blog.csdn.net/shulianghan/article/details/18964835:

Java类型 与 类型签名对照表 : 注意 boolean 与 long 不是大写首字母, 分别是 Z 与 J,  类是L全限定类名, 数组是[元素类型签名;
-- 类的签名规则 :L + 全限定名 + ;三部分, 全限定类名以 / 分割;
Java类型 类型签名
boolean Z
byte B
char C
short S
int I
long J
float F
double D
L全限定类名
数组 [元素类型签名


Java数据类型 C数据类型 JNI数据类型对比 : 32位 与 64位机器可能会有出入;

Java数据类型 C本地类型 JNI定义别名
int long jint/jsize
long __int64 jlong
byte signed char jbyte
boolean unsigned char jboolean
char unsigned short jchar
short short jshort
float float jfloat
double doyble jdouble
object'
_jobject jobject

数据类型表示方法 : int数组类型 jintArray , boolean数组 jbooleanArray ...




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章