JNI

目前接触到的终端产品基本都是:C/C++写内核Android/IOS包一层皮
OC和C/C++可以混编,java和C/C++需要依赖jni桥接。

jni需要掌握两个点:

  • 如何桥接
  • 如何进行数据转换

1. jni桥接

  1. 在XXX.java中定义native方法作为接口,不需要在java中实现。
  2. 针对XXX.java生成C/C++头文件XXX.h,该头文件包含了XXX.java中所有的native函数定义。
  3. 建立C/C++的.dll或.so工程,引用jni.h、jni_md.h、XXX.h。
  4. 新建XXX.cpp并实现XXX.h中的方法,编译生成动态链接库XXX.dll或XXX.so
  5. 在XXX.java中使用语句加载XXX.dll或XXX.so后,即可调用native方法。

在这里插入图片描述

2. jni数据转换

XXX.h头文件中定义的函数为

JNIEXPORT void JNICALL method_name
	(JNIEnv *env, jobject obj, ...){
}

env包含了大量可调用的函数。
若方法为static,则obj为类;
若方法非static,则obj为类对象

2.1 基本数据类型

基本数据类型可以直接用。
jni.h中的定义:

typedef unsigned char   jboolean;	// 1byte
typedef unsigned short  jchar;		// 2byte
typedef short           jshort;		// 2byte
typedef float           jfloat;		// 4byte
typedef double          jdouble;	// 8byte
typedef long jint;					// 4byte
typedef __int64 jlong;				// 8byte
typedef signed char jbyte;			// 1byte
typedef jint            jsize;		// 4byte

2.2 string

获取长度

// 获取unicode编码下的string长度
jsize len = env->GetStringLength(str);
// 获取utf-8编码下的string长度
jsize len = env->GetStringUTFLength(str);

访问元素,无法修改,一定要释放

// 获取string长度
jsize len = env->GetStringLength(str);		// unicode编码模式
jsize len = env->GetStringUTFLength(str);	// utf-8编码模式

// 获取char
const jchar *data = env->GetStringChars(str, NULL);		// unicode编码模式
const char *data = env->GetStringUTFChars(str, NULL);	// utf-8编码模式

// 访问
for(int i = 0;i<len;i++){
	data[i];
}

// 释放
env->ReleaseStringChars(str,data);		// unicode编码模式
env->ReleaseStringUTFChars(str,data);	// utf-8编码模式

创建新string

jstring str = env->NewString(unicode, len);	// unicode编码模式
jstring str = env->NewStringUTF(utf);		// utf-8编码模式

2.3 Class

获取class类

jclass _jclass = env->FindClass("类路径,例如java/lang/String");// 根据路径得到类
jclass _jclass = env->GetObjectClass(_jobject);	// 根据类对象得到类

得到类对象中的属性

// 得到_jclass类中名字为name,描述为sig的属性
jfieldID _fieldID = env->GetFieldID(_jclass, "name", "sig");
// 基于属性的数据类型选择Get方法,得到该属性的值
jint value = env->GetIntField(_jobject, _fieldID);		// int型
jbyte value = env->GetByteField(_jobject, _fieldID);		// byte型
jchar value = env->GetCharField(_jobject, _fieldID);		// char型
jobject value = env->GetObjectField(_jobject, _fieldID);	// class型
...

调用类对象中的方法

// 得到_jclass类中名字为name,描述为sig的方法
jmethodID _methodID = env->GetMethodID(_jclass, "name", "sig");
// 基于返回值的数据类型选择call方法进行函数调用
env->CallVoidMethod(_jobject, _methodID, ...);	
jboolean ret = env->CallBooleanMethod(_jobject, _methodID, ...);
jchar ret = env->CallCharMethod(_jobject, _methodID, ...);
jbyte ret = env->CallByteMethod(_jobject, _methodID, ...);
jshort ret = env->CallShortMethod(_jobject, _methodID, ...);
jint ret = env->CallIntMethod(_jobject, _methodID, ...);
jlong ret = env->CallLongMethod(_jobject, _methodID, ...);
jfloat ret = env->CallFloatMethod(_jobject, _methodID, ...);
jdouble ret = env->CallDoubleMethod(_jobject, _methodID, ...);
jobject ret = env->CallObjectMethod(_jobject, _methodID, ...);

备注:
name应与类对象中的方法/属性名一致
方法/属性sig可通过命令javap -s -p XXX.class得到
在这里插入图片描述

2.4 数组

jni.h定义了9种array,且都继承了_jarray类

class _jbooleanArray : public _jarray {};
class _jbyteArray : public _jarray {};
class _jcharArray : public _jarray {};
class _jshortArray : public _jarray {};
class _jintArray : public _jarray {};
class _jlongArray : public _jarray {};
class _jfloatArray : public _jarray {};
class _jdoubleArray : public _jarray {};
class _jobjectArray : public _jarray {};

访问array,无法修改,一定要释放

// 获取array的长度
jsize len = env->GetArrayLength(_jArray);
// 依据array中元素的数据类型选择对象的函数,获取array的首地址
jboolean *data = env->GetBooleanArrayElements(_jarray ,NULL);
jbyte *data = env->GetByteArrayElements(_jarray ,NULL);
jchar *data = env->GetCharArrayElements(_jarray ,NULL);
jshort *data = env->GetShortArrayElements(_jarray ,NULL);
jint *data = env->GetIntArrayElements(_jarray ,NULL);
jlong *data = env->GetLongArrayElements(_jarray ,NULL);
jfloat *data = env->GetFloatArrayElements(_jarray ,NULL);
jdouble *data = env->GetDoubleArrayElements(_jarray ,NULL);
jobject *data = env->GetObjectArrayElement(_jarray ,NULL);
// 遍历访问array
for(int i = 0; i<len; i++){
	data[i];
}
// 释放
env->ReleaseBooleanArrayElements(array,data,mode);
env->ReleaseByteArrayElements(array,data,mode);
env->ReleaseCharArrayElements(array,data,mode);
env->ReleaseShortArrayElements(array,data,mode);
env->ReleaseIntArrayElements(array,data,mode);
env->ReleaseLongArrayElements(array,data,mode);
env->ReleaseFloatArrayElements(array,data,mode);
env->ReleaseDoubleArrayElements(array,data,mode);

创建array,做了实验,不需要释放

jbooleanArray array = env->NewBooleanArray(_size);
jcharArray array = env->NewCharArray(_size);
jbyteArray array = env->NewByteArray(_size);
jshortArray array = env->NewShortArray(_size);
jintArray array = env->NewIntArray(10);
jlongArray array = env->NewLongArray(_size);
jfloatArray array = env->NewFloatArray(_size);
jdoubleArray array = env->NewDoubleArray(_size);

对array赋值

env->SetBooleanArrayRegion(array, start, len, *buf);
env->SetCharArrayRegion(array, start, len, *buf);
env->SetByteArrayRegion(array, start, len, *buf);
env->SetShortArrayRegion(array, start, len, *buf);
env->SetIntArrayRegion(array, start, len, *buf);
env->SetLongArrayRegion(array, start, len, *buf);
env->SetFloatArrayRegion(array, start, len, *buf);
env->SetDoubleArrayRegion(array, start, len, *buf);
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值