2017-10-10 143 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目录