Android开发经验谈Android技术知识Android-NDK/JNI

JNI编程指南(一):基本类型、字符串、数组

2018-11-01  本文已影响14人  码农叔叔

前言

对于任何一个初学者,学习JNI都是从Java和C/C++之间如何传递数据,以及数据类型之间是如何相互映射开始。

Native方法和C函数原型

看点代码

package com.net168.xxx
class Simple {
    private native String testA(String str);
    private native static void testA(int num);
}

//C端源码
JNIEXPORT jstring JNICALL
    Java_Com_net168_xxx_Simple_testA(JNIEnv *env, jobject thiz, jstring str);
JNIEXPORT void JNICALL
    Java_Com_net168_xxx_Simple_testB(JNIEnv *env, jclass clz, jint num);

知识点

类型映射

本地方法声明中的参数类型在C语言中都有对应的类型,具体对应表格如下:

java类型 本地类型 描述
boolean jboolean C/C++8位整型
byte jbyte C/C++带符号的8位整型
char jchar C/C++无符号的16位整型
short jshort C/C++带符号的16位整型
int jint C/C++带符号的32位整型
long jlong C/C++带符号的64位整型e
float jfloat C/C++32位浮点型
double jdouble C/C++64位浮点型
Object jobject 任何Java对象,或者没有对应java类型的对象
Class jclass Class对象
String jstring 字符串对象
Object[] jobjectArray 任何对象的数组
boolean[] jbooleanArray 布尔型数组
byte[] jbyteArray 比特型数组
char[] jcharArray 字符型数组
short[] jshortArray 短整型数组
int[] jintArray 整型数组
long[] jlongArray 长整型数组
float[] jfloatArray 浮点型数组
double[] jdoubleArray 双浮点型数组

知识点

字符串处理

jstring转c语言字符串

JNIEXPORT jstring JNICALL
    Java_Com_net168_xxx_Simple_testA(JNIEnv *env, jobject thiz, jstring jstr)
{
    jboolean isCopy;
    //获取utf-8格式的c字符串
    const char *str1 = env->GetStringUTFChars(jstr, &isCopy);
    //do something
    env->ReleaseStringUTFChars(jstr, str1);

    //获取Unicode格式的c字符串
    const jchar *str2 = env->GetStringChars(jstr, &isCopy);
    //do something
    env->ReleaseStringChars(jstr, str2);
}

知识点


构造新字符串

const char *str = "hello";
//将str转为utf-8编码的jstring字符串
jstring jstr = env->NewStringUTF(str);
const jchar *str1 = env->GetStringChars(jstr, NULL);
//将str1转为unicode编码的jstring字符串
jstring jstr1 = env->NewString(str1, env->GetStringLength(jstr));

知识点


其他字符串函数

//临界区字符串函数
const jchar *str = env->GetStringCritical(jstr, NULL);
//do something
env->ReleaseStringCritical(jstr, str);

//预先分配缓存字符串函数
jchar *str1 = static_cast<jchar *>(malloc(5 * sizeof(jchar)));
env->GetStringRegion(jstr, 0, 5, str1);
//do something
//自己释放str1 malloc的内存
free(str1);

知识点

数组

基本类型数据数组

JNIEXPORT void JNICALL
    Java_Com_net168_xxx_Simple_testC(JNIEnv *env, jobject thiz, jintArray jarray)
{
    //获取整个数组内容
    jint *array1 = env->GetIntArrayElements(jarray, NULL);
    //do something
    env->ReleaseIntArrayElements(jarray, array1, 0);

    //获取数组长度
    jsize len = env->GetArrayLength(jarray);

    //预分配获取数组内容
    jint buf[10];
    env->GetIntArrayRegion(jarray, 0, 10, buf);
    //栈区域不用手动释放内存

    //在开始索引3的位置,开始更新5个数据
    env->SetIntArrayRegion(jarray, 3, 5, buf);

    //临界区获取数组内容
    jint *array2 = static_cast<jint *>(env->GetPrimitiveArrayCritical(jarray, NULL));
    //do something
    env->ReleasePrimitiveArrayCritical(jarray, array2, 0);
}

知识点


对象数组

JNIEXPORT void JNICALL
    Java_Com_net168_xxx_Simple_testD(JNIEnv *env, jobject thiz, jobjectArray jarray)
{
    //获取jobjectArray的第一个jobject
    jobject obj1 = env->GetObjectArrayElement(jarray, 0);

    //将obj1设置到数组的第二个索引的位置
    env->SetObjectArrayElement(jarray, 1, obj1);
}

知识点

结语

后续会陆续发布多篇JNI更加深入的文章。

本文同步发布于简书CSDN

End!

上一篇 下一篇

猜你喜欢

热点阅读