【Android NDK 开发】JNI 方法解析 ( 字符串数组参数传递 | 字符串遍历 | 类型强转 | Java 字符串与 C 字符串转换 | 字符串释放 )
文章目錄
- I . C/C++ 中的 Java 字符串?dāng)?shù)組類型
- II . 獲取字符串?dāng)?shù)組長(zhǎng)度
- III . 獲取字符串?dāng)?shù)組元素
- IV . 類型強(qiáng)轉(zhuǎn) ( jobject -> jstring )
- V . 字符串轉(zhuǎn)換 ( jstring -> char* )
- VI . 字符串釋放
- VII . 部分代碼示例
I . C/C++ 中的 Java 字符串?dāng)?shù)組類型
JNI 中 C/C++ 代碼里的 Java 字符串?dāng)?shù)組類型 : jobjectArray ;
① JNI 類型現(xiàn)狀 : 在 JNI 中沒(méi)有定義 Java 字符串?dāng)?shù)組類型 , 只定義了 Java 字符串類型 jstring ;
② Object 對(duì)應(yīng) jobject : 在 C/C++ 環(huán)境中 jobject 類型對(duì)應(yīng) Java 中的 Object 類型 , Java 中字符串也是 Object 類型的 ;
③ 字符串?dāng)?shù)組類型 : 因此在 C/C++ 環(huán)境中使用 對(duì)象數(shù)組 jobjectArray 來(lái)當(dāng)做 字符串?dāng)?shù)組類型 ;
II . 獲取字符串?dāng)?shù)組長(zhǎng)度
1 . 前提條件 : Java 層傳入?yún)?shù) jobjectArray stringArray , 該參數(shù)對(duì)應(yīng) Java 代碼中的 String[] stringArray 參數(shù) ;
下面的 GetArrayLength 方法的 stringArray 參數(shù) , 就是 jobjectArray 類型的 ;
2 . 獲取字符串?dāng)?shù)組長(zhǎng)度 代碼示例 : 其中返回值 jsize 是 int 類型的別名 ;
jsize stringArrayLength = env->GetArrayLength(stringArray);GetArrayLength 方法詳細(xì)解析參考如下內(nèi)容 :
GetArrayLength 方法解析 ( 獲取 jarray 數(shù)組長(zhǎng)度 )
III . 獲取字符串?dāng)?shù)組元素
C/C++ 代碼中獲取指定索引的 Java 字符串?dāng)?shù)組類型的元素 ;
1 . 調(diào)用方法 : 調(diào)用 JNIEnv * env 的 GetObjectArrayElement 方法 , 可以獲取指定索引的 jobject 引用類型變量 ;
2 . 方法原型 :
struct _JNIEnv {/* _JNIEnv 結(jié)構(gòu)體中封裝了 JNINativeInterface 結(jié)構(gòu)體指針 */const struct JNINativeInterface* functions;...// 最終 調(diào)用的 還是 JNINativeInterface 結(jié)構(gòu)體中封裝的 GetObjectArrayElement方法jobject GetObjectArrayElement(jobjectArray array, jsize index){ return functions->GetObjectArrayElement(this, array, index); }... }3 . GetObjectArrayElement 參數(shù)說(shuō)明 :
① jobjectArray array 參數(shù) : 由 Java 層傳入的 Java 對(duì)象數(shù)組 ;
② jsize index 參數(shù) : 要獲取的數(shù)組元素的索引值 ;
4 . 獲取對(duì)象數(shù)組指定元素代碼示例 :
其中的參數(shù) stringArray 是 jobjectArray 類型的 , 由 JNI 方法傳入 ;
其中的參數(shù) i 是 int 類型的 , 是要獲取的元素的索引值 , 從 0 開(kāi)始計(jì)數(shù) ;
jobject string_object = env->GetObjectArrayElement(stringArray, i);IV . 類型強(qiáng)轉(zhuǎn) ( jobject -> jstring )
將 jobject 轉(zhuǎn)為 jstring 類型 : string_object 是 jobject 類型變量 ;
// 2.2 將 jobject 類型強(qiáng)轉(zhuǎn)成 jstring 類型 , 這兩個(gè)都代表了 Java 的數(shù)據(jù)類型jstring string_java = static_cast<jstring>(string_object);詳細(xì)內(nèi)容參考下面博客 :
【C++ 語(yǔ)言】類型轉(zhuǎn)換 ( 轉(zhuǎn)換操作符 | const_cast | static_cast | dynamic_cast | reinterpret_cast | 字符串轉(zhuǎn)換 )
V . 字符串轉(zhuǎn)換 ( jstring -> char* )
1 . GetStringUTFChars 方法 : 將 jstring 類型字符串 ( Java 中的字符串 ) 轉(zhuǎn)為 char* 類型字符串 ( C/C++ 中的字符串 ) ;
2 . 函數(shù)原型 : jstring string 參數(shù)是 Java 通過(guò) JNI 傳入的 , 代表 Java 字符串 ;
struct _JNIEnv {/* _JNIEnv 結(jié)構(gòu)體中封裝了 JNINativeInterface 結(jié)構(gòu)體指針 */const struct JNINativeInterface* functions;...// 最終 調(diào)用的 還是 JNINativeInterface 結(jié)構(gòu)體中封裝的 GetStringUTFChars 方法const char* GetStringUTFChars(jstring string, jboolean* isCopy){ return functions->GetStringUTFChars(this, string, isCopy); }... }3 . jboolean* isCopy 參數(shù) : 該參數(shù)用于指定將 jintArray 類型的變量 , 轉(zhuǎn)為 jint * 指針類型的變量 , 新的指針變量的生成方式 ;
① 將 該參數(shù)設(shè)置成指向 JNI_TRUE 的指針 : 將 int 數(shù)組數(shù)據(jù)拷貝到一個(gè)新的內(nèi)存空間中 , 并將該內(nèi)存空間首地址返回 ;
② 將 該參數(shù)設(shè)置成指向 JNI_FALSE 的指針 : 直接使用 java 中的 int 數(shù)組地址 , 返回 java 中的 int 數(shù)組的首地址 ;
③ 將 該參數(shù)設(shè)置成 NULL ( 推薦 ) : 表示不關(guān)心如何實(shí)現(xiàn) , 讓系統(tǒng)自動(dòng)選擇指針生成方式 , 一般情況下都不關(guān)心該生成方式 ;
④ jboolean 類型取值 : jboolean 的取值只能是 0 和 1 , 也可以使用 JNI_FALSE 和 JNI_TRUE 宏定義 ;
#define JNI_FALSE 0 #define JNI_TRUE 14 . jstring 字符串轉(zhuǎn)換 為 char* 字符串示例 :
const char *string_c = env->GetStringUTFChars(string_java, JNI_FALSE);VI . 字符串釋放
1 . ReleaseStringUTFChars 方法 : 將 Java 字符串 和 C/C++ 字符串都釋放 ;
2 . 函數(shù)原型 :
jstring string 參數(shù)是 Java 通過(guò) JNI 傳入的 , 代表 Java 字符串 ;
const char* utf 參數(shù)是通過(guò) GetStringUTFChars 方法將上面的 Java 字符串轉(zhuǎn)成的 C/C++ 字符串 ;
struct _JNIEnv {/* _JNIEnv 結(jié)構(gòu)體中封裝了 JNINativeInterface 結(jié)構(gòu)體指針 */const struct JNINativeInterface* functions;...// 最終 調(diào)用的 還是 JNINativeInterface 結(jié)構(gòu)體中封裝的 ReleaseStringUTFChars 方法void ReleaseStringUTFChars(jstring string, const char* utf){ functions->ReleaseStringUTFChars(this, string, utf); }... }VII . 部分代碼示例
部分代碼示例 :
#include <jni.h> #include <string>//導(dǎo)入日志庫(kù) #include <android/log.h>//定義日志宏 , 其中的 __VA_ARGS__ 表示可變參數(shù) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,"JNI",__VA_ARGS__);...extern "C" JNIEXPORT void JNICALL Java_kim_hsl_jni_MainActivity_jniArrayTest(JNIEnv *env, jobject instance, jintArray intArray_,jobjectArray stringArray) {...// II . 引用類型數(shù)組操作 ( 獲取字符串?dāng)?shù)組 )// 1 . 獲取字符串?dāng)?shù)組長(zhǎng)度jsize stringArrayLength = env->GetArrayLength(stringArray);// 2 . 遍歷字符串?dāng)?shù)組for(int i = 0; i < stringArrayLength; i ++) {/*2.1 獲取 jobject 數(shù)組中第 i 個(gè)元素注意 : 獲取的是 jobject 類型變量函數(shù)原型 : jobject GetObjectArrayElement(jobjectArray array, jsize index)jobjectArray array 參數(shù) : 是 Java 層傳入的 Java 對(duì)象數(shù)組 參數(shù) , 即 Native 層的調(diào)用函數(shù)的參數(shù)jsize index 參數(shù) : 對(duì)象元素的索引值 , 取值范圍 0 ~ stringArrayLength - 1返回值 : 返回的是 jobject 類型的變量*/jobject string_object = env->GetObjectArrayElement(stringArray, i);// 2.2 將 jobject 類型強(qiáng)轉(zhuǎn)成 jstring 類型 , 這兩個(gè)都代表了 Java 的數(shù)據(jù)類型jstring string_java = static_cast<jstring>(string_object);/*2.3 將 jstring 類型轉(zhuǎn)為 char* 類型jstring 類型簡(jiǎn)介 :class _jobject {};class _jstring : public _jobject {};typedef _jstring* jstring;由上面可見(jiàn) , jstring 只是 繼承了 _jobject 類 , 沒(méi)有任何實(shí)現(xiàn) , 是一個(gè)空類因此需要借助 C/C++ 方法 將 java 類型的 jstring 字符串 其轉(zhuǎn)為 C/C++ 類型的 char* 類型字符串轉(zhuǎn)換函數(shù)原型 : void ReleaseStringUTFChars(jstring string, const char* utf)*/const char *string_c = env->GetStringUTFChars(string_java, 0);// 2.4 打印 轉(zhuǎn)換后的 字符串值__android_log_print(ANDROID_LOG_INFO, "JNI_TAG", "打印字符串?dāng)?shù)組元素 : %d . %s", i, string_c);// 2.5 釋放 char* 字符串env->ReleaseStringUTFChars(string_java, string_c);}}代碼執(zhí)行結(jié)果 :
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 數(shù)組元素 : 0 . 1 01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 數(shù)組元素 : 1 . 2 01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 數(shù)組元素 : 2 . 666 01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 數(shù)組元素 : 3 . 888 01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 數(shù)組元素 : 4 . 95555 01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印字符串?dāng)?shù)組元素 : 0 . Hello 01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印字符串?dāng)?shù)組元素 : 1 . World 01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印字符串?dāng)?shù)組元素 : 2 . Hanshuliang 01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: Java 層 jniArrayTest 執(zhí)行完畢后 , int[] intArray 數(shù)組內(nèi)容 : [8888, 8888, 8888, 8888, 8888]限于篇幅就不再貼完整代碼了 , 去下載博客資源有全套的 JNI 文檔教程 , 及博客源碼
總結(jié)
以上是生活随笔為你收集整理的【Android NDK 开发】JNI 方法解析 ( 字符串数组参数传递 | 字符串遍历 | 类型强转 | Java 字符串与 C 字符串转换 | 字符串释放 )的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Android NDK 开发】JNI
- 下一篇: 【Android NDK 开发】JNI