如何在NDK上将本机运行时库与dlopen集成? 我的本机C++项目,我必须设置一个预编译共享库的运行时加载,它可以在客户端启动时使用配置改变。在android上调用dlopen的正确方式是什么?无论我做什么,如果我不在我的Android.mk文件中将此库定义为预编译库,dlopen永远无法打开任何共享库,如下所示: LOCAL_PATH := $(call my-dir) LOCAL_CFLAGS += -DDEBUG LOCAL_CFLAGS += -DANDROID include $(CLEAR_VARS) LOCAL_MODULE := bar LOCAL_SRC_FILES := bar/bar.cpp LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/bar include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := native_activity LOCAL_SRC_FILES := main.cpp LOCAL_LDLIBS := -llog LOCAL_LDLIBS += -landroid LOCAL_SHARED_LIBRARIES := bar LOCAL_STATIC_LIBRARIES += android_native_app_glue include $(BUILD_SHARED_LIBRARY) $(call import-module, android/native_app_glue)

如何在NDK上将本机运行时库与dlopen集成? 我的本机C++项目,我必须设置一个预编译共享库的运行时加载,它可以在客户端启动时使用配置改变。在android上调用dlopen的正确方式是什么?无论我做什么,如果我不在我的Android.mk文件中将此库定义为预编译库,dlopen永远无法打开任何共享库,如下所示: LOCAL_PATH := $(call my-dir) LOCAL_CFLAGS += -DDEBUG LOCAL_CFLAGS += -DANDROID include $(CLEAR_VARS) LOCAL_MODULE := bar LOCAL_SRC_FILES := bar/bar.cpp LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/bar include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := native_activity LOCAL_SRC_FILES := main.cpp LOCAL_LDLIBS := -llog LOCAL_LDLIBS += -landroid LOCAL_SHARED_LIBRARIES := bar LOCAL_STATIC_LIBRARIES += android_native_app_glue include $(BUILD_SHARED_LIBRARY) $(call import-module, android/native_app_glue),android,android-ndk,Android,Android Ndk,在本机activity main类中,我尝试使用以下内容加载库: void* lib = dlopen("/system/lib/armeabi-v7a/libbar.so", RTLD_NOW); if (lib == NULL) { fprintf(stderr, "Could not dlopen(\"libbar.so\"): %s\n", dlerror()); exit(1); }else{ LOGI("Library successfully loa

在本机activity main类中,我尝试使用以下内容加载库:

void* lib = dlopen("/system/lib/armeabi-v7a/libbar.so", RTLD_NOW);
if (lib == NULL) {
    fprintf(stderr, "Could not dlopen(\"libbar.so\"): %s\n",
    dlerror());
    exit(1);
}else{
    LOGI("Library successfully loaded!");

    if (dlsym(lib, "bar") == NULL) {
        fprintf(stderr, "Symbol 'bar' is missing from shared library!!\n");        
    }else{
        LOGI("Library symbol found!"); 
    }

    int x = bar(25);
    LOGI("Bar return value: %i", x);
}
这个实现的缺点是它不是真正的运行时加载,因为我必须在JNI启动时使用JAVA机制加载这个库

如果我从Android.mk中删除了bar库预编译定义,在启动时禁用JNI加载,并将预编译库的副本添加到它应该位于的systems/lib文件夹中(与使用预编译定义存储预编译库的位置相同),则加载库失败。我已经检查了apk包,它按预期在lib文件夹中包含手动复制的库


为什么这行不通?是否可以对外部预编译库执行严格的本机运行时库加载?确保将我的库添加到apk包的最佳方法是什么

Android上的最佳策略是从Java加载所有本机库,即使您根据一些运行时规则选择加载哪些库。您可以使用dlsym(0,…)然后在那里访问导出的函数


APK builder将拾取所有。因此它在
libs/armeabi-v7a
中找到的文件,安装程序将它们解压缩到
/data/data//lib
目录中。

我的问题是,我必须移植到android的本机应用程序使用库管理器在运行时加载依赖项。由于这个原因,JAVA不是一个选项……JAVA总是一个选项。您可能需要对原始库管理器进行调整,以适应Android安全和分发模型。其中一个选项是将此管理器的一部分实现为对Java函数的回调,该函数将只调用System.LoadLibrary()。在C中实现等效的
System.LoadLibrary()
,主要问题是位置
/data/data//lib
是一个没有文档记录的实现细节,这可能会在操作系统的任何未来版本中发生变化,或者由于某个原始设备制造商的一些调整。谢谢你的提示,我会查看这个。同时我解决了这个问题,关于你关于图书馆位置的信息。如果我将“/data/data//lib”作为库搜索路径,我就可以成功地使用dlopen加载外部预编译库。我是第二种情况(my.so加载其他.so),我按照您所说的方式修复了它!除非您使用根设备,或者从头开始构建平台,否则无法将库部署到
/system/lib
。无论如何,你可能是在混合APK的组织方式(使用共享库的
/libs/armeabi-v7a
/libs/x86
等文件夹)和Android安装应用程序的方式,提取与设备ABI匹配的库到
/data/data//lib
目录。