我需要在我的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());
}
我收到以下错误:
Error:error: cannot find -ldynamic
Error:(19) undefined reference to 'rsqrt(float)'
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版。任何帮助都非常感谢。
答案 0 :(得分:0)
为了在Android环境中使用CMake加载您的库,您必须在native-lib CMakeLists.txt中添加以下代码:
set(LIBS_DIR ${CMAKE_SOURCE_DIR}/../jniLibs)
add_library(DYNAMIC_LIB SHARED IMPORTED)
set_target_properties(DYNAMIC_LIB PROPERTIES
IMPORTED_LOCATION ${LIBS_DIR}/${ANDROID_ABI}/lidynamic.so)
target_link_libraries(native-lib DYNAMIC_LIB)
并在native-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'
}
}
答案 1 :(得分:0)
使用-L将sysroot lib目录添加到LDFLAGS,因为如果我没记错,libdynamic也依赖于libc,libdl,并且至少应该需要libm。
路径应该是:
$ NDK /平台/ android-(平台的版本)/ arch-(体系结构)/ usr / lib中
答案 2 :(得分:0)
我能够使用Android.mk而不是cmake使其工作。我正在发布Android.mk和gradle build的配置和内容,以防任何人需要它。
在“app”下创建一个“jni”文件夹。创建另一个自定义文件夹“yourlibs”,并将所有预先构建的库放在相应“TARGET_ARCH_ABI”文件夹中的“yourlibs”文件夹中。例如,在我的情况下:
现在请按照以下步骤操作:
在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”语句。