美文网首页
JNI-NDK(Linux平台使用NDK打包so库)

JNI-NDK(Linux平台使用NDK打包so库)

作者: 大虾啊啊啊 | 来源:发表于2022-09-01 14:08 被阅读0次

    1、源文件

    将以下简单的一个C程序打包成动态SO库提供给安卓使用。

    • 头文件
    //
    // Created by DELL on 2022/9/1.
    //
    #include <stdio.h>
    
    #ifndef UNTITLED_DEMO_H
    #define UNTITLED_DEMO_H
    
    #endif //UNTITLED_DEMO_H
    
    int testDemo();
    
    
    • 实现文件
    //
    // Created by DELL on 2022/9/1.
    //
    #include "demo.h"
    int testDemo() {
        printf("Hello, Get World!\n");
        return 889;
    }
    int main(){
        testDemo();
    }
    
    #include <stdio.h>
    
    int testStatic() {
        printf("Hello, Get World!\n");
        return 3333;
    }
    
    
    #include <stdio.h>
    
    int get() {
        printf("Hello, Get World!\n");
        return 199;
    }
    
    

    2、Linux平台打SO动态库

    (1)Linux平台下载安装NDK

    wget https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip? hl=zh_cn

    (2)重命名解压

    修改成.zip mv android-ndk-r17c-linux-x86_64.zip?hl=zh_cn android-ndk-r17c-linux- x86_64.zip
    解压unzip android-ndk-r17c-linux-x86_64.zip

    (3)配置全局环境变量

    vim /etc/profile

    #配置NDK路径
    export NDK="/root/NDK/tool/android-ndk-r17c"
    #配置GCC
    export NDK_GCC_x86="/root/NDK/tool/android-ndk-r17c/toolchains/x86-4.9/prebuilt/linux-x86_64/bin/i686-linux-android-gcc"
    export NDK_GCC_x64="/root/NDK/tool/android-ndk-r17c/toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-gcc"
    export NDK_GCC_arm="/root/NDK/tool/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc"
    export NDK_GCC_arm64="/root/NDK/tool/android-ndk-r17c/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc"
    
    #配置寻找库文件、头文件、asm
    #arch-arm  arch-arm64  arch-mips64  arch-x86  arch-x86_64 
    
    export NDK_CFIG_x86="--sysroot=/root/NDK/tool/android-ndk-r17c/platforms/android-21/arch-x86 -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include  -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include/i686-linux-android"
    export NDK_CFIG_x64="--sysroot=/root/NDK/tool/android-ndk-r17c/platforms/android-21/arch-x86_64 -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include  -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include/x86_64-linux-android"
    export NDK_CFIG_arm="--sysroot=/root/NDK/tool/android-ndk-r17c/platforms/android-21/arch-arm -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include  -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include/arm-linux-androideabi"
    export NDK_CFIG_arm64="--sysroot=/root/NDK/tool/android-ndk-r17c/platforms/android-21/arch-arm64 -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include  -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include/aarch64-linux-android"
    
    #配置AR 用于打包静态库
    export NDK_AR_x86="/root/NDK/tool/android-ndk-r17c/toolchains/x86-4.9/prebuilt/linux-x86_64/bin/i686-linux-android-ar"
    export NDK_AR_x64="/root/NDK/tool/android-ndk-r17c/toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-ar"
    export NDK_AR_arm="/root/NDK/tool/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar"
    export NDK_AR_arm64="/root/NDK/tool/android-ndk-r17c/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar"
    
    
    image.png

    (4)打动态so库

    以上配置了四个平台、x86、x86_64、arm,arm64。使用相应的环境变量打包生成相应平台的so库。例如打x86平台的so执行如下:

    $NDK_GCC_x86 $NDK_CFIG_x86 -fPIC -shared demo.c -o libdemo.so
    

    因此四个平台打包的命令分别如下:

    $NDK_GCC_x86 $NDK_CFIG_x86 -fPIC -shared demo.c -o libdemo.so
    $NDK_GCC_x64 $NDK_CFIG_x64 -fPIC -shared test.c -o libtest.so
    $NDK_GCC_arm $NDK_CFIG_arm -fPIC -shared test.c -o libtest.so
    $NDK_GCC_arm64 $NDK_CFIG_arm64 -fPIC -shared test.c -o libtest.so
    

    这样我们就生成了对于平台的so库。


    image.png

    (4)打静态a库

    #打包静态库
    $NDK_GCC_x86 $NDK_CFIG_x86 -fPIC -c static.c -o libstatic.o
    $NDK_AR_x86 rcs -o  libstatic.a  libstatic.o
    
    image.png

    3、动态so库、静态a库集成到Android环境

    (1)将so库集成到jnilibs中

    image.png

    (2)将静态a库集成as中

    image.png

    (3)配置Cmake

    #cmake_minimum_required(VERSION 3.4.1) # 最低支持Cmake版本
    
    cmake_minimum_required(VERSION 3.10.2)# 最低支持Cmake版本
    # Declares and names the project.
    project("jni_02")
    
    #NDK集成C库流程
    #1、导入C库头文件 inc
    include_directories("inc")
    
    #2、配置总库,也就是最终打包到APK里的库
    file(GLOB allCPP *.c *.h *.cpp)
    add_library(
            native-lib # Sets the name of the library 给最终打包到APK的C库起名称 native-lib
            SHARED # Sets the library as a shared library.//设置库为动态共享库
            ${allCPP} # Provides a relative path to your source file(s).//导入所有源文件
    )
    #导入静态库【第二方式】 可读性更强,代码多
    add_library(static STATIC IMPORTED)
    set_target_properties(static PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libstatic.a)
    
    # 导入动态库 【第二方式】 可读性更强,代码多
    #add_library(getndk SHARED IMPORTED)
    #set_target_properties(getndk PROPERTIES
            #IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libgetndk.so)
    
    #导入动态库 【第一种方式】简单,不易理解 ,CMAKE_ANDROID_ARCH_ABI会自动匹配当前的CPU架构,
        ##设置so文件夹
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")
    
    
    
    #这种方式是一个个添加
    #add_library( # Sets the name of the library.
    #        jni_01
    #        # Sets the library as a shared library.
    #        SHARED
    #        # Provides a relative path to your source file(s).
    #        native-lib.cpp extern-lib.cpp)
    
    #4、链接具体的库,到我们的 libnative-lib.so总库
    target_link_libraries(
            native-lib
            #${log-varAAAA}
            log # 自动寻找  # 具体的库 链接到 libnative-lib.so里面去
            fmod # 具体的库 链接到 libnative-lib.so里面去
            fmodL # 具体的库 链接到 libnative-lib.so里面去
            test # 具体的库 链接到 libnative-lib.so里面去
            demo # 具体的库 链接到 libnative-lib.so里面去
            static # 具体的库 链接到 libnative-lib.so里面去
    )
    
    
    
    

    (3)配置Gadle

    image.png

    (4)测试

    • 初始化加载lib
      static {
            System.loadLibrary("native-lib");
            System.loadLibrary("test");
            System.loadLibrary("demo");
        }
    
    • JNI测试
     binding.btnMySo.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    testMySo();
                }
            });
        native void testMySo();
    
    // 我先声明 int get(),运行后,你自己去找 实现(libtest.so 库里面的实现),如果找不到报错
    extern "C" { // 由于库 是C编写的,必须采用C的编译方式
    extern int get();
    }
    extern "C" { // 由于库 是C编写的,必须采用C的编译方式
    extern int testDemo();
    }
    extern "C" { // 由于库 是C编写的,必须采用C的编译方式
    extern int testStatic();
    }
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_it_jni_102_MainActivity_testMySo(JNIEnv *env, jobject thiz) {
        LOGD("test my so")
        jint  result = testDemo();
        jint  result2 = get();
        jint  result3 = testStatic();
        LOGD("testDemo value is %d",result);
        LOGD("get value is %d",result2);
        LOGD("testStatic value is %d",result3);
    
    }
    
    2022-09-01 14:34:09.596 4375-4375/com.it.jni_02 D/Native: test my so
    2022-09-01 14:34:09.596 4375-4375/com.it.jni_02 D/Native: testDemo value is 889
    2022-09-01 14:34:09.596 4375-4375/com.it.jni_02 D/Native: get value is 199
    2022-09-01 14:34:09.596 4375-4375/com.it.jni_02 D/Native: testStatic value is 3333
    

    相关文章

      网友评论

          本文标题:JNI-NDK(Linux平台使用NDK打包so库)

          本文链接:https://www.haomeiwen.com/subject/yhcsnrtx.html