2017-10-10 115 views
0

我需要在我的android項目中使用自定義預構建共享庫(構建於獨立ndk上,作爲libdynamic.so)。我在路徑src/main中創建了一個文件夾「jniLibs」,然後在「armeabi」「armeabi-v7a」「x86」「x86_64」中創建了4個文件夾。我已將預建的庫放入所有這4個文件夾中。在Android Studio中使用預構建的共享庫

現在來自我的本地代碼,我想調用這個庫的一個函數。以下列方式(在的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我裏面積聚其他條目(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推動和android殼庫。這是使用Android Studio的apk版本造成的問題。我正在使用Android Studio版本2.3.3。任何幫助,高度讚賞。

回答

0

我能使其工作使用Android.mk而不是cmake。我發佈了Android.mk和gradle build的配置和內容,以防萬一需要它。

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

  • JNI/yourlibs/armeabi/libdynamic.so
  • JNI/yourlibs/armeabi-V7A/libdynamic.so
  • JNI/yourlibs/86/libdynamic.so
  • JNI/yourlibs/x86_64的/ libdynamic.so

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

  1. 創建一個 「C」 F在你要調用在「libdynamic.so」中定義的函數的「jni」文件夾中。添加必要的頭文件到您創建的「C」文件中。對我來說, 「uselib.c」 和 「header.h」
  2. 創建一個名爲 「Android.mk」 中的 「JNI」 文件夾內

添加以下內容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更新版本(應用程序)文件中使用的 「Android.mk」,而不是cmake的:

Inside 「的機器人=> defaultConfig」

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

內部「Android」的

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

這將使一個名爲「使用-LIB」庫,它使用「libdynamic.so」,它會包裝既APK的lib文件夾中的庫。你可以使用apk分析器(Android Studio => Build => Analyze Apk ...)來檢查它。要使用 「使用-lib的」 使用JNI調用,如:

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

public native String stringFromJNI(); 

注:我刪除的extern 「C」 語句從C代碼。

0

爲了加載通過CMake在Android的環境資料庫,你將不得不添加以下代碼在本地-lib中的CMakeLists.txt:

設置你的庫路徑

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

添加庫導入

add_library(DYNAMIC_LIB SHARED IMPORTED)

組庫升ocation每個ABI

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

鏈接庫導入到目標

target_link_libraries(native-lib DYNAMIC_LIB)

並在本機的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' 
    } 
} 
+0

嘿泰坦,謝謝你的回答;但使用你的配置我收到以下錯誤:「錯誤:錯誤:'../../../../../jniLibs/x86/libdynamic.so',需要'../../ .. /../build/intermediates/cmake/debug/obj/x86/libnative-lib.so',缺少並且沒有已知規則使其成爲「 –

+0

你有沒有jni.srcDirs = ['src/main/jniLibs /']在native-lib/build.gradle中?因爲這是告訴編譯器你的共享庫在哪裏。 – Titan

0

添加SYSROOT lib目錄到LDFLAGS使用-L因爲如果我正確地記得libdynamic也依賴於libc,libdl,並且至少應該要求libm。

的路徑應該是:

$ NDK /平臺/ android-(平臺版本)/ arch-(架構)/ usr/lib目錄

相關問題