自己用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'
}

 

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