Android框架基础-JNI

1.NDK与JNI的区别:

NDK是为了方便开发基于JNI的应用而提供的一套开发和编译工具集;

JNI是一套编程接口,可以运用在应用层,应用框架层,用以实现Java代码与本地代码的交互。

2.编程的模型结构:

第一步:Java层声明Native方法。

第二步:JNI层实现Java层声明的Native方法,在JNI层可以调用底层库或者毁掉Java层方法。

第三步:加载JNI层代码编译后生成的共享库。



JNI中的JNIEnv是什么:

在C++中:JNIEnv就是struct_JNIEnv。JNIEnv* env等价于struct _JNIEvn* env,在调用JNI函数的时候,只需要env->FindClass(JNIEnv*,const char*),就会间接调用JNINativeInterface结构体里定义的函数指针,而无需先对env解引用。

在C中:JNIEnv就是const struct JNINativeInterface*.JNIEnv* env实际等价于const struct JNINativeInterface** env,因此要先解引用得到*env,才能调用到JNINativeInterface结构体里面定义的函数指针。解引用调用方法即(*env)->FindClass(JNIEnv*,const char*)。

注意:JNIEnv只在当前现成合纵有笑。本地方法不能将JNIEnv从一个现成传递到另一个现成中。相同的java现成中对本地方法多次调用的时候,传递给该本地方法的JNIEnv是相同的。但是一个本地方法可以被不同的Java现成所调用,因此可以接受不同的JNIEnv。


第一节 在Java中调用JNI实现方法

Java数据与JNI数据类型转换。

(Java层调用JNI方法传递参数是Java类型需要通过dalvik虚拟机转换后才能被JNI识别。)

Java-JNI基本数据类型转换关系表
Java类型JNI类型字  长
booleanjboolean8位
bytejbyte8位
charjchar16位
shortjshort16位
intjint32位
longjlong64位
floatjfloat32位
doublejdouble64位
voidvoid 
   


JNI方法命名规则:

Java_前缀

全限定的类名

下划线(_)分隔符

增加第一参数JNIEnv* env

增加第二个参数jobject

其他参数按类型映射

返回值按类型映射

例如:

public static native boolean isLoggable(String tag, int level);

对应的JNI方法实现:

static jboolean android_util_Log_isLoggable(JNIEnv* env,jobject clazz,jstring tag,jint level){//...实现代码};

在框架层中可以采用函数注册的方式建立Java层生命方法与JNI层实现方法之间的对应关系,可以不遵守这些规则。


JNI方法签名规则:(用一个字符来识别重载方法)

JNI类型签名规则
Java类型类型签名Java类型类型签名
booleanZlongJ
byteBfloatF
charCdoubleD
shortSL全限定类名;
intI数组[元素类型签名
例如:

long fun(int n , String str,int[] arr);

对应的方法签名:

(ILjava/lang/String;[I)J


JNI操作Java对象(通过操作jobject带来操作Java对象提供的变量和方法):

FindClass和GetObjectClass

在C++中:

jclass FindClass(const char* name);//查找类信息

jclass GeObjectClass(jobject obj);//返回对象的类

在C中:

jclass (*FindClass)(JNIEnv* ,const char*);

jclass (*GetObjectClass)(JNIEnv* , jobject);

注意:通过FindClass传入要查找的类的全限定名(以“/”分隔路径)即可,之后方法返回一个jclass对象,这样就可以操作这个类的方法和变量了。


操作成员变量(域)和方法:

Java中习惯将变量成为成员变量,而不是域。为了兼容JNI命名规则和Java习惯,将域和变量等价。

操作变量=》以Log系统为例:

第一步:通过FindClass方法找到类的信息clazz;

第二步:以clazz为参数调用GetStaticFieldID(clazz,"DEBUG","I");其中DEBUG是要访问的Java域的名字,I是该域的类型签名,即整型。

第三步:GetStaticFieldID函数返回一个jfieldID,代表Java成员变量。最后将该ID传给GetStaticField方法,得到Java层的成员变量DEBUG的值。

操作方法:

与操作成员变量类似,流程如下:

FindClass->GetMethodID(返回jmethodID)->Call<Type>Method

其中Type为方法的修饰符,如public ,private 等等


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值