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