自己用NDK編寫C++方法生成全平臺so庫

作者:譚東

軟件環境:Windows+Android Studio+CMake

這裏記錄一下自己編寫的簡單C++方法,然後再編寫JNI方法,最後通過CMake編譯成全平臺so庫使用。

整個項目結構:

爲了方便,我們可以用Android Studio的創建Native C++這個來創建項目,這樣會自動給我們生成一個比較完善的目錄結構。

首先我們需要在項目的app/libs下新建一個include目錄。這個目錄的作用就是用來包含我們的C/C++庫,當然也可以自己編寫C/C++方法邏輯。例如這裏我們放置了兩個庫JsonCpp庫的libjson目錄和自己寫的libencrypt源碼目錄。一個完整的C/C++庫源碼一般包含.c/.cpp和.h文件。.c/.cpp爲源碼邏輯實現文件,.h爲抽象的方法頭文件。

我們看下自己寫的encrypt.cpp文件:

#include "encrypt.h"
#include <string>

std::string getEncryptString(std::string text) {
    return "Encrypt:" + text + ":endl";
}

頭文件encrypt.h:

#ifndef ENCRYPTLIB_ENCRYPT_H
#define ENCRYPTLIB_ENCRYPT_H
#define _GLIBCXX_USE_CXX11_ABI 0

#include <string>
std::string getEncryptString(std::string text);

#endif //ENCRYPTLIB_ENCRYPT_H

很簡單,我就是想測試下so庫調用我們的C++方法。

編寫JNI方法,調用我們的libencrypt庫的方法:

#include <jni.h>
#include <string>
#include "../../../libs/include/libencrypt/encrypt.h"

extern "C" {
using namespace std;

//這個方法爲定義的調用我們的libencrypt寫的C++方法
JNIEXPORT jstring JNICALL
Java_com_google_encryptlib_MainActivity_getEncryptText(JNIEnv *env,
                                                       jobject, jstring text) {
    std::string license = getEncryptString(
            env->GetStringUTFChars(text, 0));//env->GetStringUTFChars(text, NULL)
    return env->NewStringUTF(license.c_str());
}

}

編寫配置CMakeLists.txt:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../libs)

message("test ndk message")

add_library( # Sets the name of the library.
        native-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        native-lib.cpp)

add_library( # Sets the name of the library.
        encrypt

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        ../../../libs/include/libencrypt/encrypt.cpp)

#file(GLOB SRC_LIST "*.cpp" "../../../libs/include/libjson/*.cpp")
#add_library( # Sets the name of the library.
#        json
#
#        # Sets the library as a shared library.
#        SHARED
#
#        # Provides a relative path to your source file(s).
#        ${SRC_LIST})
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

add_library(json
        SHARED
        IMPORTED)
set_target_properties(json
        PROPERTIES IMPORTED_LOCATION
        ../../../../src/main/jniLibs/${ANDROID_ABI}/libjson.so)
message(${ANDROID_ABI})
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        native-lib
        encrypt
        json
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

include_directories(libs/include)

build.gradle文件:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.google.encryptlib"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

 

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