當前位置:
首頁 > 最新 > 《NDK入門》之 C 大雜燴&JNI入門

《NDK入門》之 C 大雜燴&JNI入門

前言

Look up at the stars, not down at your feet.

感謝公眾號「伯特說」博主成兵前輩在公眾號推廣、寫作上的建議,以後文章就沒那麼丑了!

本篇文章主要對C語言中一些零碎知識複習,以及JNI簡單入門。(看本篇文章,建議已經熟悉C語言以及JNI開發流程)。

1、函數指針

我們直接使用示例代碼來解釋,有如下代碼:

運行程序:

如果理解了基本數據類型指正定義方式,這裡肯定是難不住你的。我們總結定義函數指針的步驟吧:

定義函數的指針

賦值 pf = add

引用 pf(3,5);

2、結構體

如果對JAVA比較熟悉的話,那麼結構體簡直就是小菜一碟了。就直接把結構體理解成java中的javaBean就行了,通過示例代碼加深印象:

struct Student stu = ;表示給結構體裡面的「屬性」賦值,並且得到一個類似JAVA對象的stu類型變數,如果想要使用「屬性」,也同樣跟java代碼很類似。

定義結構體類型的指針 就類比基本類型定義方式即可,如果想要列印「屬性」值,有兩種方式可以做到。其中第二種方式將會在後面的JNI文章中大量出現:pStu->age 在計算機內部會被轉換為 (* pStu).age。運行程序:

在C中還有一個聯合體的概念,這裡就不做討論了,在JNI中使用不多。聯合體類似於java中的Object ,在聯合體中聲明的變數使用的都是同一塊內存空間 。

3、枚舉

對於枚舉來說,C中跟Java中非常的類似了。通過簡單代碼理解一下:

注意上面,枚舉項的第一項初始化值為0,那麼後面的枚舉項自動 +1 ,列印Sunday應該是6、運行程序:

4、JNI開發知識點及流程總結

這塊內容,建議您已經熟悉了JNI開發流程了,屬於一個概括性的總結。

交叉編譯

在一個平台下,編譯出另一個平台能夠執行的二進位的代碼

平台:windows,mac os,linux

處理器:x86,arm,mips

交叉編譯的原理

源代碼->編譯->鏈接->可執行程序

模擬其他平台的特性

交叉編譯的工具鏈

多個工具的集合,一個工具使用完後接著調用下一個工具

常見工具

NDK:native developement kit:開發jni必備,就是模擬其他平台特性來編譯代碼的工具

CDT:C/C++ developement tools:高亮顯示c語言關鍵字

cygwin:一個模擬器,可以再windows下運行linux指令

NDK目錄結構

docs:幫助文檔

build/tools:linux的批處理文件

platforms:我們編譯c代碼需要使用的頭文件和類庫 jni.h文件(很重要)

prebuilt:預編譯使用的二進位可執行文件

sample:jni的使用例子

source:ndk的源碼

toolchains:工具鏈

ndk-build.cmd:編譯打包c代碼的一個指令(很重要,類似adb)

使用jni

在項目根目錄下創建jni文件夾

在jni文件中創建一個c文件

在java代碼中,創建一個本地方法helloFromC

在jni中定義函數實現這個方法,函數名必須為

返回一個字元串,用c定義一個字元串

把c的字元串轉換成java的字元串

在jni中創建Android.mk文件

在c文件中添加頭文件

在jni文件夾下執行ndk-build.cmd指令。會生成一個so文件

java代碼中載入so類庫,調用本地方法【static靜態代碼塊中寫入載入類庫邏輯】

常見錯誤

findLibrary returned null

CPU平台不匹配

載入類庫時,寫錯類庫名字

本地方法找不到

忘記載入類庫

c代碼中方法名寫錯了

說明你的工程中缺少Android.mk文件

你沒有載入so類庫

找不到類庫,載入類庫時,寫錯類庫名字或者CPU平台不匹配,模擬器不匹配(比如模擬器使用了x86架構)

07-13 02:23:14.268: E/AndroidRuntime(1549): Caused by: java.lang.UnsatisfiedLinkError: Couldn"t load hello1: findLibrary returned null

參數遺漏了

error: parameter name omitted(遺漏)。這個參數是c代碼中的方法沒有寫入參數。如下: jstring Javacomitydl_helloworld1MainActivityhelloFromC(JNIEnv* , jobject )

方法調錯了

jni/Hello1.c:9:17: error: "struct JNINativeInterface const" has no member named "NewStringUTF1"

如果vm掛掉 也是方法調錯了(c文件中的方法寫錯了)

javah

5 Android.mk文件說明

6 jni開發的簡便流程

配置NDK環境。看第2步

聲明本地方法

集成ndk開發環境 選Windows -->preferences->Android-->找到你自己ndk環境

Android Tools ----> 添加本地支持 add native support.會自動生成jni目錄以及裡面的文件內容。其中.cpp和.mk文件系統自動生成了。

把默認生成的cpp格式的文件變成.C

要把Android.mk文件的LOCALSRCFILES 改一下

寫C代碼 如果想要提示 直接看我資料準備的圖片

C代碼寫好後 不用ndk-build 你只需要給他一鎚子 ,就會在lib目錄下面生成so庫文

在靜態代碼塊中載入類庫 System.loadLibrary。名字一定要和Android.mk文件中的LOCAL_MODULE一致才行。

5、簡單案例

本節內容會介紹Java調用C代碼的案例:

需求,用c語言實現登錄校驗功能,java代碼調用該功能。

按照上面的流程,給出MainActivity代碼:

其中public native int login(String pwd);是本地方法。

在jni目錄下:

Android.mk:

然後是hello.c代碼(實現了登錄校驗功能):

詳細的代碼注釋解釋的很詳細了。

jint JNICALL Java_com_itydl_login_MainActivity_login

(JNIEnv *env, jobject obj, jstring jstr)方法就是本地方法,而真正的校驗方法在login(pwd)方法中。返回值為200表示校驗成功,返回值400表示校驗失敗。在Activity端直接判斷返回值即可。

本文顯得很枯燥,建議在了解了jni開發流程基礎上再來看比較好理解~


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Android進階之劍 的精彩文章:

TAG:Android進階之劍 |