如何在 NDK 上将本机运行时库与 dlopen 集成? [英] How to integrate native runtime library with dlopen on NDK?

查看:15
本文介绍了如何在 NDK 上将本机运行时库与 dlopen 集成?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于我的本机 c++ 项目,我必须设置一个预编译共享库的运行时加载,客户端可以在启动时使用配置对其进行更改.在android上调用dlopen的正确方法是什么?无论我做什么,dlopen 都无法打开任何共享库,如果我没有在我的 Android.mk 文件中将此库定义为预编译库,如下所示:

For my native c++ project I've to set up a runtime loading of a precompiled shared library, which could be changed by client side on start up using configurations. What is the proper way of calling dlopen on android? No matter what I do, dlopen can never open any shared library, if I not define this library as precompiled library in my Android.mk file like this:

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)

在我的原生活动主类中,我尝试使用以下方式加载库:

In my native activity main class I try to load the library with:

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

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

    int x = bar(25);
    LOGI("Bar return value: %i", x);
}

这个实现的缺点是它不是真正的运行时加载,因为我还必须在使用 JAVA 机制的 JNI 启动时加载这个库.

The disadventage of this implementation is that is not really a runtime loading, because I've to load this library also on JNI startup using JAVA mechanisms.

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

If I remove the bar library precompile defintions from Android.mk, disable JNI loading on startup and add a copy of the precompiled library to the systems/lib folder where it should be (same place where it is stored using precompile definitions), the loading of the library fails. I've checked the apk package it contains my manually copied library at lib folder as expected.

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

Why this will not work? Is it possible to perform a strict native runtime library loading of an external precompiled library? And what is the best way to ensure that my library is added to the apk package?

推荐答案

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

The best strategy on Android is to load all native libraries from Java, even if you choose which libraries to load, by some runtime rules. You can use dlsym(0, ...) then to access exported functions there.

APK builder 将拾取它在 libs/armeabi-v7a 中找到的所有 .so 文件,安装程序会将它们解压到 /data/data/<your.package>/lib 目录.

APK builder will pick up all .so files it finds in libs/armeabi-v7a and the installer will unpack them into /data/data/<your.package>/lib directory.

这篇关于如何在 NDK 上将本机运行时库与 dlopen 集成?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆