JNI使用記錄-Android Studio創建Native C++項目

JNI概述

JNI,全稱爲Java Native Interface,即Java本地接口,通過使用 Java本地接口書寫程序,可以確保代碼在不同的平臺上方便移植。

使用Android Studio新建一個項目,選擇Native C++

在這裏插入圖片描述
在這裏插入圖片描述

關於module的build.gradle

android {
    //省略了其他代碼
    
    defaultConfig {

        externalNativeBuild {
            cmake {
                //值爲""是因爲創建項目選的ToolChain Default
                cppFlags ""
            }
        }
    }

    externalNativeBuild {
        cmake {
            //外部構建腳本路徑
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        sample_text.text = stringFromJNI()
    }

    external fun stringFromJNI(): String


    companion object {
        init {
            System.loadLibrary("native-lib")
        }
    }
}

我新建的kotlin項目,如果是java項目的話,就不需要使用伴生對象(companion 關鍵字修飾的對象)和external關鍵字。在java中使用static和native關鍵字:


static {
	System.loadLibrary("native-lib");
 }
 
public native String stringFromJNI();

native-lib.cpp

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_phz_myapplication_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

分析:“Java_com_phz_myapplication_MainActivity_stringFromJNI”字段是不是很熟。
com.phz.myapplication是包名,MainActivity是當前活動,stringFromJNI是方法名。還有返回了String,都跟Activity對應上了。所以除了so文件,cpp文件也可以直接加載,然後使用他的方法。

CMakeLists.txt

以cpp目錄下的CMakeLists.txt爲例(去掉了註釋)

cmake_minimum_required(VERSION 3.4.1)

add_library(	native-lib		SHARED		native-lib.cpp )

find_library(	log-lib		log )

target_link_libraries(	native-lib		${log-lib} )

關於cmake命令,可以參考文檔:cmake-commands

add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [source1] [source2 ...])
            
target_link_libraries(<target> ... <item>... ...)

整個調用流程

  1. Gradle調用外部構建腳本CMklist.txt。
  2. CMake按照腳本中的命令將C++源文件native-lib.cpp編譯成native-lib.so動態庫,並把它編譯到APK中。
  3. 運行時首先加載native-lib.so,然後調用so中的stringFromJNI方法,最後把這個方法返回的值顯示在TextView上。

關於build之後編譯出的so路徑

app/build/intermediates/cmake

在這裏插入圖片描述

CMakeLists.txt添加多個依賴和單依賴

關於路徑

c語言相關資源一般都是放在cpp文件夾下。記得之前有在module的build.gradle設置cmake的path。(path “src/main/cpp/CMakeLists.txt”)我們先新建一個文件夾haizhuo,添加haizhuo-lib.cpp文件。

在這裏插入圖片描述

之後,我們可以通過修改CMakeLists.txt把haizhuo-lib.cpp加進依賴,有2種方式,可以選擇編譯成一個庫文件還是二個庫文件。

1. 把haizhuo-lib.cpp同native-lib.cpp一起編譯到到native-lib包裏,只需要修改:
add_library(native-lib  HARED  native-lib.cpp   haizhuo/haizhuo-lib.cpp)
2. 編譯成2個庫文件,不僅需要修改CMakeLists.txt,還需要添加System.loadLibrary(String libname)
cmake_minimum_required(VERSION 3.4.1)

add_library(native-lib  SHARED  native-lib.cpp)
add_library(haizhuo-lib  SHARED  haizhuo/haizhuo.cpp)
find_library(log-lib    log)

target_link_libraries(native-lib    ${log-lib} )
target_link_libraries(haizhuo-lib   ${log-lib} )
companion object {
        init {
            System.loadLibrary("native-lib")
            System.loadLibrary("haizhuo-lib")
        }
    }

補充:關於能添加的源文件類型

//關於源文件,下面的都能加進依賴
.c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp  .hxx .in .txx
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章