語言有的時候表述一件事真的很乏力,可能我理解的並沒有完全清楚的表達出來,如果你看到了,並且理解不了,那麼,就多琢磨吧
1、CMakeLists.txt篇(注意,這個文件的內容識別不區分大小寫的):
1)設置輸出.so文件目錄設置:
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../outputJniLibs/${ANDROID_ABI})
說明:
PROJECT_SOURCE_DIR指的是當前CMakeLists.txt文件所在目錄,
/..是上一級目錄的意思,
ANDROID_ABI是指在app.build文件android -》defaultConfig -》externalNativeBuild -》cmake 下的abiFilters定義的一組目錄
舉個栗子:
如果當前CMakeLists.txt文件在app文件夾下,並且,那麼abiFilters值爲"x86","x86_64",那麼上面的設置就會把生 成的.so文件放在本項目的 頂級目錄 文件夾下的outputJniLibs中的x86文件夾和x86_64文件夾,不過實驗結果好像是, 運行到什麼架構的手機上就會在相應架構的文件夾下生成.so庫,其他的文件夾倒不會生成,不知原因爲何
2)只生成一個.so文件的設置:
(1)設置生成庫的源代碼:
add_library(NativeHelper SHARED src/main/cpp/one/com_liuchaoya_c_NativeHelper.cpp)
說明:這個方法有三個參數,分別以空格分割。
NativeHelper 要生成的.so庫的名稱,
SHARED 是否作爲共享庫,這個一般不用動,我是不會動,
src/main/cpp/one/com_liuchaoya_c_NativeHelper.cpp 生成庫所需要的源文件
(2)設置要鏈接的目標庫:target_link_libraries(NativeHelper ${log-lib}).
說明:這個方法有兩個參數,分別以空格分割。
NativeHelper 需要鏈接的目標庫,
${log-lib} 要鏈接的目標庫,這個log-lib庫是在NDK中定義好了的,直接鏈上,毫不猶豫
3)生成多個.so文件的設置:
(1)直接添加如下代碼(測試只生成兩個庫)
ADD_SUBDIRECTORY(src/main/cpp/one)
ADD_SUBDIRECTORY(src/main/cpp/two)
對這裏的參數 路徑進行一下解釋:
前提:這裏測試的源碼分別在app下的src/main/cpp/one和src/main/cpp/two文件夾中。
說明:這個路徑仍然是跟着CMakeLists.txt文件的位置走的,當CMakeLists.txt文件在app下時,
這個路徑就是src/main/cpp/*, *代表目錄名,
當CMakeLists.txt在app的src/main/cpp下時,則可以直接這樣寫
ADD_SUBDIRECTORY(one)
ADD_SUBDIRECTORY(two)
就不用要前面的src/main/cpp/了
(2)設置子目錄src/main/cpp/one和src/main/cpp/two下的CMakeLists.txt文件:
src/main/cpp/one下:
add_library(NativeHelper SHARED com_liuchaoya_c_NativeHelper.cpp)
target_link_libraries(NativeHelper log)
參數意義已經在上面的2)和3)中講過
src/main/cpp/two下:
add_library(NativeCHelper SHARED com_liuchaoya_c_NativeCHelper.c)
target_link_libraries(NativeCHelper log)
以上兩個文件內容的區別就是指定了庫的名稱和源文件路徑,僅此而已。
2、java調用工具類:
1)不要忘了加載庫
static {
System.loadLibrary("庫名稱");
}
2)方法最好是靜態,方便調用
3、cpp源碼:
1)需要將方法包括在
extern "C"{...} 中,不然調用不到,會報沒有對應實現了的方法的錯誤
2)方法名遵循 以下規則:Java_包名_工具類名_方法名
例如:Java_com_liuchaoya_c_NativeHelper_getNativeString,這裏
com_liuchaoya_c是包名(要加上工具類所在各級目錄名),
NativeHelper是工具類名,
getNativeString是方法名,
3)返回值用法:
以返回一個字符串爲例:
cpp代碼 中是 return env->NewStringUTF("字符串");
c代碼 中是 return (*env)->NewStringUTF(env, "字符串");
注意區別
4、c源碼:
1)不需要將方法包括在
extern "C"{...} 中,直接寫方法就行
extern "C"的意思就是將包括的代碼以C語言進行處理編譯,而本身就是c的話就無需轉換
2)其他同cpp基本相同,唯一一點返回值的區別在cpp中已經說過