Android JNI學習04-AndroidStudio3.6 java 向 C++函數傳遞數組

鏈接:https://pan.baidu.com/s/1zB9r5WwuTMIPNMlYl5HlvA 
提取碼:5ndl

在MainActivity中添加如下代碼

可以發現,報紅色,AndroidStudio希望我們繼續創建sendIntArrayToJNI()的C++函數。

快捷生成對應的C++函數

鼠標放到紅色上面:alt + enter

生成的C++函數如下

extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_jnistudy_MainActivity_sendIntArrayToJNI(JNIEnv *env, jobject thiz,
                                                         jintArray int_array) {
    // TODO: implement sendIntArrayToJNI()
}

這裏對這部分代碼再次說明下。

JNIEXPORT

這是一個固定的標識,表示當前這個函數可以被JNI框架調用

jstring

這是JNI的返回值的類型,這個類型和java的sendIntArrayToJNI返回值類型是對應的,如下

java中的sendIntArrayToJNI返回值類型是String,C++函數中的返回值類型也該是String,唯一區別是,在JNI裏,String 是 用 jstring表示的。

假如,java中的sendIntArrayToJNI返回值類型是int,那麼JNIEXPORT 後面就是jint ,在java裏的每一個數據類型,在jni中都會有一個數據類型對應,如下是java和JNI 數據類型的對應表

JNICALL

這個是用於指定,C++函數中形參值的入棧順序。以當前JNI函數sendIntArrayToJNI()爲例,它有如下3個參數

這個函數的形參值入棧順序有2種,一種是從右向左,一種是從左向右。

如何理解呢?

從右向左:就是JNI在調用sendIntArrayToJNI()時,會將傳遞給sendIntArrayToJNI()的形參值,先保存到棧裏,保存的順序就是從右開始,也就是從右邊開始,依次將形參值,存放到棧裏,sendIntArrayToJNI()在執行的時候,自己去這個棧裏,按照順序,自己去尋找對應的形參值。

從左向右:就是將形參值,從左邊開始,依次存放到棧裏。

這是一個固定的寫法,各位採用默認的方式就行了。默認是從右向左將形參值放到棧裏。

JNI函數的形參

生成的JNI函數,有3個形參

有2個是固定的,每個創建的JNI函數都會有,另一個參數是我們在java層定義的。

env

的值是JVM傳遞過來的,它代表的是當前JVM環境,它提供了很多功能的函數調用,具體後面再說。

thiz

代表的是JNI函數對應的java函數所在的類對象,有點繞扣,比如sendIntArrayToJNI()在MainActivity中定義的,那麼這個

thiz就代表MainActivity這個對象

int_array

代表的就是java層sendIntArrayToJNI()的int[]

說了這麼多,下面開始獲取java傳遞過來的int[]

先在MainActivity中,添加如下代碼

在JNI函數中獲取傳遞過來的數組數據

1.獲取數組指針的首地址

jintArray是一個class,它裏面並沒有提供任何方法,能夠直接獲取到數組中的元素,因此我們只能通過

env->GetIntArrayElements()來獲取jintArray中所保存的數組元素的首地址。只要找到了首地址,我們就能以指針的形式,遍歷數組了。

2.以指針的方式遍歷數組

代碼如下

想要遍歷,首先就得獲取數組的長度,env->GetArrayLength()就能獲取到數組的長度。

現在基本已經完成了遍歷的功能,現在我們來把結果輸出來,驗證下。

日誌工具

在jni中,想要將結果打印出來,直接用print,肯定是不行的,需要用JNI中自帶的日誌函數

__android_log_print

使用這個函數,先要導入頭文件

#include <android/log.h>

示例代碼如下

這裏說明下,__android_log_print 的形參

第一個參數:是日誌的優先級,類似於Logcat中的日誌級別

第二個參數,是日誌的Tag,像java中的Log.e("JNI",“msg”)

第三個參數,就是具體要輸出的內容,裏面可以使用佔位符

第四個參數:就是替換第三個參數中的佔位符。

由於這個JNI函數,還有一個返回值,我們就隨便返回一個內容吧

完整代碼如下

extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_jnistudy_MainActivity_sendIntArrayToJNI(JNIEnv *env, jobject thiz,
        jintArray int_array) {
    jint *javaArray = env->GetIntArrayElements(int_array, NULL);

    int32_t length = env->GetArrayLength(int_array);
    for (int k = 0; k < length; ++k) {
        int tmp = *(javaArray+k);
        __android_log_print(ANDROID_LOG_ERROR,"JNI","數組的值:%d",tmp);
    }

    std::string hello = "測試數組傳遞";
    return env->NewStringUTF(hello.c_str());
}

現在程序就寫好了,接下來就運行下吧

Android JNI學習05-AndroidStudio3.6 java 向 JNI函數傳遞字符串數組

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章