Android Studio NDK開發案例二 JNI包含多個cpp文件

        上一章節我們學會了如何使用Android Studio開發JNI,但是上一章節針對的是單個cpp文件,我們做項目開發時肯定不止一個cpp文件,假如這些cpp文件能夠放在一個單獨的文件夾下面肯定會更方便我們的操作,但是這些該如何實現呢?其實我們只需要修改CMakeLists.txt及重新定向CMakeLists.txt的路徑就可以實現。

該案例在上一章節創建的工程案例中改動實現,上一章節的案例:https://blog.csdn.net/weixin_40779546/article/details/84791694

1、在cpp目錄下創建文件夾helloworld,將native-lib.cpp移動到helloworld文件夾,並在helloworld文件夾下創建.cpp和.h文件,結構如下:

./cpp/helloworld
          |
          +--- native-lib.cpp
          |
          +--- helloworld.cpp
          |
          +--- helloworld.h
          |
          +--- includes.h
          |          

源碼如下:

//native-lib.cpp


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

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

extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_administrator_myapplication_MainActivity_helloworldJNI(
        JNIEnv* env,
        jobject instance) {
    std::string hello = helloworld();
    return env->NewStringUTF(hello.c_str());
}

 

//helloworld.cpp


//
// Created by taxiangxuezi on 2018/12/6 0006.
//

#include "includes.h"

/*******************************************************************************
* 函數名稱: char * helloworld(void)
* 函數功能:
* 輸入參數:
* 輸出參數:
* 返回值  :
*******************************************************************************/
char * helloworld(void)
{
    char *ptr = "hello world";

    return ptr;
}

//helloworld.h



//
// Created by taxiangxuezi on 2018/12/6 0006.
//

#ifndef MYAPPLICATION_HELLOWORLD_H
#define MYAPPLICATION_HELLOWORLD_H

extern char * helloworld(void);

#endif //MYAPPLICATION_HELLOWORLD_H

 

//includes.h


//
// Created by taxiangxuezi on 2018/12/6 0006.
//

#ifndef MYAPPLICATION_INCLUDES_H
#define MYAPPLICATION_INCLUDES_H

#include "helloworld.h"

#endif //MYAPPLICATION_INCLUDES_H

這樣將所有源碼放在一個文件夾,方便管理和移植。

2、源文件準備好後,開始修改編譯鏈接規則。我們知道在創建JNI工程時,在app/目錄下會自動生成CMakeLists.txt,如下圖:

此處爲了今後使用方便,我們使用自己生成的CMakeLists.txt,重新生成的CMakeLists.txt位置結構如下:

./cpp/helloworld
   |      |
   |      +--- native-lib.cpp
   |      |
   |      +--- helloworld.cpp
   |      |
   |      +--- helloworld.h
   |      |
   |      +--- includes.h
   |      |  
   |      +--- CMakeLists.txt 
   |      | 
   |         
   |
   +--- CMakeLists.txt   
   |
  

兩個CMakeLists.txt的源碼如下:

// ./cpp/CMakeLists.txt



#指定需要CMAKE的最小版本
cmake_minimum_required(VERSION 3.4.1)

#C的編譯選項是 CMAKE_C_FLAGS
#指定編譯參數,可選
SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")

#設置生成的so動態庫最後輸出的路徑
#set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})

#設置頭文件搜索路徑(和此txt同個路徑的頭文件無需設置),可選
#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/common)

#指定用到的系統庫或者NDK庫或者第三方庫的搜索路徑,可選。
#LINK_DIRECTORIES(/usr/local/lib)

#添加子目錄,將會調用子目錄中的CMakeLists.txt
ADD_SUBDIRECTORY(helloworld)
// ./cpp/helloworld/CMakeLists.txt



#生成so動態庫

# 查找當前目錄下的所有源文件,並保存到 DIR_LIB_SRCS 變量
aux_source_directory(. DIR_LIB_SRCS)

# 生成鏈接庫
ADD_LIBRARY(native-lib SHARED ${DIR_LIB_SRCS})

# 導入當前目錄下的所有頭文件
include_directories(.)

find_library(log-lib log)

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

aux_source_directory 查找在某個路徑下的所有源文件。

aux_source_directory(< dir > < variable >)

  蒐集所有在指定路徑下的源文件的文件名,將輸出結果列表儲存在指定的變量中。該命令主要用在那些使用顯式模板實例化的工程上。模板實例化文件可以存儲在Templates子目錄下,然後可以使用這條命令自動收集起來;這樣可以避免手工羅列所有的實例。

  使用該命令來避免爲一個庫或可執行目標寫源文件的清單,是非常具有吸引力的。但是如果該命令貌似可以發揮作用,那麼CMake就不需要生成一個感知新的源文件何時被加進來的構建系統了(也就是說,新文件的加入,並不會導致CMakeLists.txt過時,從而不能引起CMake重新運行。——譯註)。正常情況下,生成的構建系統能夠感知它何時需要重新運行CMake,因爲需要修改CMakeLists.txt來引入一個新的源文件。當源文件僅僅是加到了該路徑下,但是沒有修改這個CMakeLists.txt文件,使用者只能手動重新運行CMake來產生一個包含這個新文件的構建系統。

 

打開\MyApplication\app\build.gradle,修改CMakeLists.txt路徑,源碼如下:

    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
        }
    }

這樣在編譯時就會指定src/main/cpp/CMakeLists.txt,並按照其規則編譯程序,而app目錄下的CMakeLists.txt則會失效,不用刪除它也沒影響。

編譯,生成so庫。

3、打開MainActivity.java,按照下圖修改代碼:

4、在虛擬機運行,運行結果如下:

 

 

相關文章:https://blog.csdn.net/b2259909/article/details/58591898

 

 

 

 

 

 

 

 

 

 

 

 

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