Android NDK开发入门

typedef int64_t jlong; /* signed 64 bits */typedef float jfloat; /* 32-bit IEEE 754 */typedef double jdouble; /* 64-bit IEEE 754 */[](()3.2 引用数据类型如果使用C++语言编写,则所有引用派生自jobject根类,如下所示。class _jobject {};class _jclass : public _jobject {};cla
摘要由CSDN通过智能技术生成

typedef int64_t jlong; /* signed 64 bits */

typedef float jfloat; /* 32-bit IEEE 754 */

typedef double jdouble; /* 64-bit IEEE 754 */

[](()3.2 引用数据类型

如果使用C++语言编写,则所有引用派生自jobject根类,如下所示。

class _jobject {};

class _jclass : public _jobject {};

class _jstring : public _jobject {};

class _jarray : public _jobject {};

class _jobjectArray : public _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 _jthrowable : public _jobject {};

JNI使用C语言时,所有引用类型都使用jobject。

[](()4,JNI的字符串处理

[](()4.1 native操作JVM

JNI会把Java中所有对象当做一个C指针传递到本地方法中,这个指针指向JVM内部数据结构,而内部的数据结构在内存中的存储方式是不可见的.只能从JNIEnv指针指向的函数表中选择合适的JNI函数来操作JVM中的数据结构。

比如native访问java.lang.String 对应的JNI类型jstring时,不能像访问基本数据类型那样使用,因为它是一个Java的引用类型,所以在本地代码中只能通过类似GetStringUTFChars这样的JNI函数来访问字符串的内容。

[](()4.2 字符串操作的示例

//调用

String result = operateString(“待操作的字符串”);

Log.d(“xfhy”, result);

//定义

public native String operateString(String str);

然后在C中进行实现,代码如下。

extern “C”

JNIEXPORT jstring JNICALL

Java_com_xfhy_jnifirst_MainActivity_operateString(JNIEnv *env, jobject thiz, jstring str) {

//从java的内存中把字符串拷贝出来 在native使用

const char *strFromJava = (char *) env->GetStringUTFChars(str, NULL);

if (strFromJava == NULL) {

//必须空检查

return NULL;

}

//将strFromJava拷贝到buff中,待会儿好拿去生成字符串

char buff[128] = {0};

strcpy(buff, strFromJava);

strcat(buff, " 在字符串后面加点东西");

//释放资源

env->ReleaseStringUTFChars(str, strFromJava);

//自动转为Unicode

return env->NewStringUTF(buff);

}

[](()4.2.1 native中获取JVM字符串

在上面的代码中,operateString函数接收一个jstring类型的参数str,jstring是指向JVM内部的一个字符串,不能直接使用。首先,需要将jstring转为C风格的字符串类型char*后才能使用,这里必须使用合适的JNI函数来访问JVM内部的字符串数据结构。

GetStringUTFChars(jstring string, jboolean* isCopy)对应的参数的含义如下:

  • string : jstring,Java传递给native代码的字符串指针。

  • isCopy : 一般情况下传NULL,取值可以是JNI_TRUE和JNI_FALSE,如果是JNI_TRUE则会返回JVM内部源字符串的一份拷贝,并为新产生的字符串分配内存空间。如果是JNI_FALSE则返回JVM内部源字符串的指针,意味着可以在native层修改源字符串,但是不推荐修改,因为Java字符串的原则是不能修改的。

Java中默认是使用Unicode编码,C/C++默认使用UTF编码,所以在native层与java层进行字符串交流的时候需要进行编码转换。GetStringUTFChars就刚好可以把jstring指针(指向JVM内部的Unicode字符序列)的字符串转换成一个UTF-8格式的C字符串。

[](()4.2.2 异常处理

在使用GetStringUTFChars的时候,返回的值可能为NULL,这时需要处理一下,否则继续往下面走的话,使用这个字符串的时候会出现问题.因为调用这个方法时,是拷贝,JVM为新生成的字符串分配内存空间,当内存空间不够分配的时候就会导致调用失败。调用失败就会返回NULL,并抛出OutOfMemoryError。JNI遇到未决的异常不会改变程序的运行流程,还是会继续往下走。

[](()4.2.3 释放字符串资源

native不像Java,我们需要手动释放申请的内存空间。GetStringUTFChars调用时会新申请一块空间用来装拷贝出来的字符串,这个字符串用来方便native代码访问和修改之类的。既然有内存分配,那么就必须手动释放,释放方法是ReleaseStringUTFChars。可以看到和GetStringUTFChars是一一对应配对的。

[](()4.2.4 构建字符串

使用NewStringUTF函数可以构建出一个jstring,需要传入一个char *类型的C字符串。它会构建一个新的java.lang.String字符串对象,并且会自动转换成Unicode编码。如果JVM不能为构造java.lang.String分配足够的内存,则会抛出一个OutOfMemoryError异常并返回NULL。

[](()4.2.5 其他字符串操作函数
  1. GetStringChars和ReleaseStringChars:这对函数和Get/ReleaseStringUTFChars函数功能类似,用于获取和释放的字符串是以Unicode格式编码的。

  2. GetStringLength:获取Unicode字符串(jstring)的长度。 UTF-8编码的字符串是以0结尾,而Unicode的不是,所以这里需要单独区分开。

  3. 「GetStringUTFLength」: 获取UTF-8编码字符串的长度,就是获取C/C++默认编码字符串的长度.还可以使用标准C函数「strlen」来获取其长度。

  4. strcat: 拼接字符串,标准C函数。如strcat(buff, "xfhy"); 将xfhy添加到buff的末尾。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值