Android JNI學習03-AndroidStudio3.6 動手實現一個java調用c++的函數

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

C或者C++的函數想要被java調用,首先我們得寫一個native方法,到時候JVM就可以通過native方法的名字去動態庫裏找對應的C或者C++函數。

先編寫一個native方法myJNIFunction(),如下

AndroidStudio還挺智能,知道我們還沒有編寫對應的C++函數,所以報了個錯,提示我們要趕快將C++函數寫好。

編寫對應的C++函數

.這時我們創建了一個空的文件,.cpp結尾的文件,表示這是一個C++的源文件。由於C++是在C的基礎上拓展而來的,因此在C++源文件裏,我們也可以寫C的代碼。

這是一個空的文件,現在我們先寫上java方法所對應的C++函數名,需要注意的是,C++的函數名不能隨便寫,你必須按照JNI指定的規則去寫,規則如下:

java_java方法的全路徑名

編寫C++函數名

具體代碼如下

這時,寫好之後,這個C++函數還需要2個參數,這兩個參數是JNI規定的,必須寫。

代碼如下

JNIENV* 和 jobject 都是JNI提供的數據類型。

env 和object就是變量名,變量名的名字可以隨便寫。

此時你發現代碼依然在報紅,說明還有問題。什麼問題呢?

JNIEnv* 和 jobject 是在jni.h中定義的數據類型,我們想要使用它,必須要包含jni.h

include <jni.h>

明白這點之後,現在我們就來包含jni.h,具體代碼如下

此時,你發現代碼依然是紅色,這又是是情況呢?

添加JNIEXPORT jstring JNICALL

由於這個函數是要被java調用的,因此還需要給它添加一個固定的標識,這個標識就是JNIEXPORT jstring JNICALL,明白之後,那我們就添加下吧,示例如下

發現還是有紅色,這又是什麼原因呢?

由於當前我們的文件是.cpp結尾的,編譯器在編譯這個文件的時候,會按照C++的標準來編譯。這本身沒錯。

但問題是jni.h這裏的函數是用C語言寫的,用C++的標準去編譯C寫的代碼肯定會有問題的,這個錯誤,其實就是不能用C++的標準去編譯C寫的代碼,明白了這點之後,就好解決了,只要我們明確告訴編譯器,在編譯這部分代碼的時候,用C的標準來編譯這個C++文件。

extern "C"  這行代碼的作用就是告訴編譯器,用C的標準來編譯C寫的代碼

添加extern "C" 

那我們就把 extern "C" 添加上去,示例如下

這時,終於沒有報紅了,說明我們寫的沒有問題了。

這時,我們再在這個c++函數裏返回一個字符串吧,代碼示例如下

此時發現string這裏報紅,說明沒有這道string所定義的實體,這時我們應該包含string所對應的頭文件

#include <string>

示例如下

#include <string>

可以發現,沒有.h,這是爲什麼呢?如果頭文件包含的是C的代碼,那麼就要寫.h。如果頭文件是C++的代碼,那麼就不需要寫.h,這算是一種約定吧。

完整代碼如下

#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_jnistudy_MainActivity_myJNIFunction(JNIEnv* env,
jobject object){
    std::string hello = "my Custom JNI Function";
    return env->NewStringUTF(hello.c_str());
}

這裏再補充一點,env 代碼的是jvm當前的環境,object是java方法所在類的實例對象。比如當前這個C++函數object就是指MainActivity這個實例對象。

將C++函數添加到動態庫裏

到目前爲止,我們已經完成了C++的函數的編寫。這時,我們還需要做一個操作,就是要把我們的函數加入到動態庫裏,因爲JVM就是在動態庫裏尋找我們的C++函數的。關鍵是怎麼加呢?

請看如下操作

在MainActivity裏,在MainActivity被載入的時候,我們已經添加了動態庫

此時,我們可以調用下我們寫的那個Native方法, 看下能否運行成功

成功之後的效果,如下

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

 

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