JNI程序編寫與簡單分析

環境準備:


建立JNI項目:

上圖中的Toolchain工具集就是由NDK包提供的一部分類,所以NDK是必須要安裝的。

默認即可。如果上面的環境準備沒有做的話,直接新建jni項目也是會有Gradle提示你安裝的。


生成目錄如下:


大致分析demo:

MainActivity做的第一件事:將要用的c++庫先導入進來,這樣我們才能調用這個庫裏面的c++方法.如果這個庫不在內存中, 我們是沒法調用的。

有了庫之後。它調了一個方法:

來,我們瞅瞅這函數和我們android開發中常寫的函數有何不同:

哦~~一般的函數沒有native字樣。爲了調c/c++相關的方法的時候要標識native。也就是說,這個方法是由C/C++提供的,即這是一個本地方法,要加上一個標識。這樣Java/kotlin就能知道要到系統的庫裏

System.loadLibrary("native-lib");

提供的這個庫裏去找相應的方法。

 

第二個不同的是:

因爲現在最新的版本用的CMake進行編譯.

以前這個不叫cpp目錄,叫jni,現在新版androidstudio改成了cpp

關於CMakeLists.txt是CMake的東西,可以參考這篇老哥的文章:https://www.cnblogs.com/sddai/p/10328977.html

文末寫了關於CMakeLists文件內容的分析。

然後看看native-lib.cpp:[典型的c++文件]

規律:包名_類名_方法名

這個名字可以自己創建,也可以通過javah工具產生。如果你對名字特別熟悉也可以自己寫。

這樣的一個命名規則 ,Java虛擬機就可以找到這個cpp方法.也就是說剛剛在mainactivity中的native函數

stringFromJNI. 它屬於Java包下的。

通過這樣去查找就可以在java虛擬機裏去找到對應的c方法。。

再看這個c方法:“

這個方法並沒有做什麼事,就是生成了一個字符串。然後把這個字符串返回回去。

拿到這個方法過後,就把這個字符串從c層轉化到了java層.然後java層拿到這個方法後就得到了字符串,然後設置給了TextView了。

所以,等會運行的時候,我們應該是能看到app啓動後顯示Hello from C++

來,讓我們運行驗證下我們的猜想:


使用JNI的時候總結:

  1. loadLibrary
  2. 實現相應的c層方法
  3. CMake,產生編譯腳本。【CMakeLists.txt就可以產生編譯腳本】

CMakeLists.txt是啥?

 

通過這個CMakeLists.txt就可以產生編譯腳本。

CMakeLists實際上是給CMake使用的.CMake會通過CMakeLists去產生我們想要的編譯腳本.在CMakeLists裏有幾個指令。

先看這個指令:

這個指令叫add_library,這指令的作用有2方面的作用,第一方面可以根據我們的c文件產生一個動態庫,其中產生的是動態庫還是靜態庫由第二個屬性決定,即我們這裏看到的SHARED。我們的庫的名字叫做native-lib,它是一個動態庫SHARED,如果是靜態庫就是STATIC.

這個動態庫是由native-lib.cpp產生的。【其實CMakeLists.txt文件裏面的英文註釋已經寫的很清楚了。】

即這個指令就是產生一個動態庫。

如果您的庫還需要依賴於其他的庫,那麼就看看這個指令:

通過這個指令去查找系統的庫,那麼這個系統的庫必須是在CMake指定的路徑下,像這裏的log就在系統的庫下。並起了個名字log-lib。

再看下一個指令:

通過這個名字就知道是鏈接的意思。即之前addlibrary指令找到的庫和find_library指令找到的log庫,將這2個庫鏈接到一起最終形成一個庫。怎麼鏈接——通過target_link_libraries指令。將誰鏈接起來了,就是將上圖中看到的native-lib和log-lib把這2個庫鏈接到一起。

如果這裏我有第3 個庫,要將第3個庫鏈接,就直接在後面加上xxx

還有一個額外問題:如果我們想要添加一個庫,這個庫並不在系統的CMake能找到的默認路徑下,這怎麼辦才能引入呢?

add_library。給庫起名字,指定共享庫還是靜態庫, import在別的地方已經編譯好的這個庫引入。

編譯FFmpeg好的庫也是通過這個指令從外部引入進來的。

 


學習JNI的基礎知識路線:

學習jni、FFmpeg等需要先掌握JNI的基礎知識,

  • JNI_C 語言基本類型
  • 輸出函數
  • 輸入函數
  • 指針【認識與深入理解】
  • 在單獨方法中互換地址
  • 函數返回一個以上的值
  • 多級指針
  • 數據
  • 輸入數組
  • 數組的取值運算
  • 靜態內存分配
  • 動態內存分配
  • 動態創建數組
  • 函數指針
  • 聯合體
  • 枚舉
  • 結構體
  • 結構體指針
  • Java調用C代碼執行運算
  • c調用Java方法返回值
  • 讓c的輸出能顯示在Logcat中
  • c調用java方法(String參數)
  • c調用java(回調靜態方法)

。。。。。。

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