鏈接: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());
}
現在程序就寫好了,接下來就運行下吧