簡體   English   中英

在Android Studio中使用預建的共享庫

[英]Using Pre-built Shared Library in Android Studio

我需要在我的Android項目中使用自定義的預構建共享庫(基於獨立ndk構建為libdynamic.so)。 我在路徑src / main中創建了一個文件夾“ jniLibs”,然后在其中創建了4個文件夾,即“ armeabi”,“ armeabi-v7a”,“ x86”,“ x86_64”。 我已經將預構建的庫放在所有這4個文件夾中。

現在,從我的本機代碼中,我想調用該庫的函數。 以以下方式(包含在cmakelists.txt中的標頭):

extern "C"
JNIEXPORT jstring JNICALL
Java_demo_co_ru_jnilibtest_MainActivity_stringFromJNI(
    JNIEnv *env,
    jobject /* this */) {

     float inv = rsqrt(3);  //FUNCTION FROM LIBRARY (libdynamic.so)

     std::string hello = "Hello ";
     return env->NewStringUTF(hello.c_str());
}

我收到以下錯誤:

  1. Error:error: cannot find -ldynamic

  2. Error:(19) undefined reference to 'rsqrt(float)'

  3. Error:error: linker command failed with exit code 1 (use -v to see invocation)

似乎共享庫未找到。 我在CMakeLists.txt中輸入了以下值

include_directories( src/main/cpp/include) #include header of libdynamic.so
target_link_libraries(native-lib dynamic)  #dependency of native-lib on libdynamic.so

我在gradle build(app)中添加了以下其他條目:

defaultConfig {
  ndk{
        abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'x86_64'
    }
}

sourceSets {
    main {
        jni.srcDirs = ['src/main/jni', 'src/main/jniLibs/']
    }
}


externalNativeBuild {
    cmake {
        path "CMakeLists.txt"
    }
}

我能夠使用android push和android shell成功運行該庫。 這是使用Android Studio的apk構建引起的。 我正在使用Android Studio版本2.3.3。 非常感謝您的幫助。

為了在Android環境中使用CMake加載您的庫,您將必須在本地庫CMakeLists.txt中添加以下代碼:

設置你的libs路徑

set(LIBS_DIR ${CMAKE_SOURCE_DIR}/../jniLibs)

添加要導入的庫

add_library(DYNAMIC_LIB SHARED IMPORTED)

設置每個ABI的庫位置

set_target_properties(DYNAMIC_LIB PROPERTIES IMPORTED_LOCATION ${LIBS_DIR}/${ANDROID_ABI}/lidynamic.so)

將導入的庫鏈接到目標

target_link_libraries(native-lib DYNAMIC_LIB)

並在本地庫build.gradle中:

defaultConfig{
    ...
    externalNativeBuild{
        // Specify the toolchain which was used to cross compile libdynamic.so because Android Studio assumes that you used clang
        arguments '-DANDROID_TOOLCHAIN=gcc'
    }
}

使用-L將sysroot lib dir添加到LDFLAGS,因為如果我沒記錯的話,libdynamic也依賴libc,libdl,並且至少應該需要libm。

路徑應為:

$ NDK /平台/ android-(平台版本)/ arch-(體系結構)/ usr / lib

我能夠使用Android.mk而不是cmake使其工作。 我發布Android.mk的配置和內容以及gradle構建,以防萬一有人需要它。

在“ app”下創建一個文件夾“ jni”。 創建另一個自定義文件夾“ yourlibs”,並將所有預先構建的庫放在相應的“ TARGET_ARCH_ABI”文件夾中的“ yourlibs”文件夾中。 例如,在我的情況下:

  • jni / yourlibs / armeabi / libdynamic.so
  • jni / yourlibs / armeabi-v7a / libdynamic.so
  • jni / yourlibs / x86 / libdynamic.so
  • jni / yourlibs / x86_64 / libdynamic.so

現在,請按照下列步驟操作:

  1. 在“ jni”文件夾中創建一個“ C”文件,從中可以調用“ libdynamic.so”中定義的函數。 將必要的頭文件添加到您創建的“ C”文件中。 對我來說,它是“ uselib.c”和“ header.h”
  2. 在“ jni”文件夾中創建一個名為“ Android.mk”的文件

在Android.mk中添加以下內容

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := yourlibs/$(TARGET_ARCH_ABI)/libdynamic.so
LOCAL_MODULE := add_prebuilt
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_SRC_FILES  := uselib.c
LOCAL_MODULE     :=  use-lib
LOCAL_SHARED_LIBRARIES := add_prebuilt
include $(BUILD_SHARED_LIBRARY)

更新gradle build(app)文件以使用“ Android.mk”而不是cmake:

里面的“ android => defaultConfig”

 ndk{
        abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'x86_64'
    }

在“ android”里面

externalNativeBuild {
    ndkBuild {
        path "jni/Android.mk"
    }
}

這將創建一個名為“ use-lib”的庫,該庫使用“ libdynamic.so”,並將這兩個庫都打包到apk的lib文件夾中。 您可以使用apk分析器(Android Studio => Build => Analyze Apk ...)進行檢查。 要使用“ use-lib”,請使用jni調用,例如:

static {
    System.loadLibrary("use-lib");
}

public native String stringFromJNI(); 

注意:我從C代碼中刪除了extern“ C”語句。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM