对于我的本机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)
在我的原生活动主类中,我尝试使用:
加载库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);
}
这个实现的缺点是它不是真正的运行时加载,因为我还要使用JAVA机制在JNI启动时加载这个库。
如果我从Android.mk中删除了bar库预编译定义,请在启动时禁用JNI加载,并将预编译库的副本添加到应该存在的systems / lib文件夹中(使用预编译定义存储它的位置相同) ,库的加载失败。我检查了apk包,它包含了我在lib文件夹中手动复制的库,如预期的那样。
为什么这不起作用?是否可以执行外部预编译库的严格本机运行时库加载?确保我的库添加到apk包的最佳方法是什么?
答案 0 :(得分:12)
Android上的最佳策略是从Java加载所有本机库,即使您根据某些运行时规则选择要加载的库。您可以使用 dlsym(0,...)然后访问那里的导出函数。
APK构建器将获取它在libs/armeabi-v7a
中找到的所有 .so 文件,安装程序会将它们解压缩到/data/data/<your.package>/lib
目录。