【发布时间】:2012-05-25 19:41:55
【问题描述】:
我在我的应用程序中集成了两个本机库 (.so)。这些库编译得很好,我也可以将它们加载到我的应用程序中。第一次调用库的本机方法时它工作正常,但如果我在 Activity 中再次调用相同的方法,应用程序将关闭。
我面临的问题与这里提到的完全相同:
http://grokbase.com/t/gg/android-ndk/1226m68ydm/app-exit-on-second-native-call
可行的解决方案是在另一个 Activity 中调用本机方法并通过 System.exit(0) 将其强制关闭。在文章之后,我尝试在成功操作后将被调用方法的指针设置为 NULL ,但这也对我没有帮助。一旦库被 System.loadLibrary() 加载,也无法卸载它。
我想在不创建新 Activity 的情况下多次调用本机方法。任何想法如何解决这个问题?
(我终于找到了解决方案……在这里)
好的,我终于找到了解决这个问题的方法。解决方案实际上非常简单。构建另一个独立的本机库(实用程序库)来加载和卸载其他库。我们需要做的是在实用程序的本机方法中使用 dlopen() 和 dlclose()。我们可以像以前一样通过 System.loadLibrary() 加载实用程序库。
所以在实用程序库的原生方法中我们需要做的是:
使用#include <dlfcn.h> // 这是调用 dlopen() 和 dlclose() 函数所必需的。
提供处理程序和函数原型:
void *handle;
typedef int (*func)(int); // define function prototype
func myFunctionName; // some name for the function
通过 dlopen() 打开库:
handle = dlopen("/data/data/my.package.com/lib/somelibrary.so", RTLD_LAZY);
获取和调用库函数:
myFunctionName = (func)dlsym(handle, "actualFunctionNameInLibrary");
myFunctionName(1); // passing parameters if needed in the call
现在通话已完成。通过 dlclose() 关闭它:
dlclose(handle);
希望这能帮助其他面临同样问题的人。
【问题讨论】:
-
你在哪里做 dlclose(handle)?我的意思是在 Activity 或 JNI 代码中?
-
它在 JNI 代码中。这是一个可通过 dlfcn.h 头文件获得的函数。
-
好的,我看到你在这个 c 类中加载和卸载了其他库。但是我应该如何将它链接到我的 Java 代码?
-
您需要了解 NDK。 link - 本教程将向您展示如何逐步完成所有操作。简而言之,一旦您的 NDK 环境准备就绪: 1. 您需要编写 C 文件。 2. 编写您的 Android.mk 文件以生成 .so - 共享库。 3. 使用 ndk 构建 .so 文件。 4. 编写 Java 类,您将在其中公开本地方法,并通过 System.loadLibrary 在静态块中加载库。
-
我想知道你是如何让 dlclose 工作的,在 ndk 文档中它清楚地指出“目前从不调用静态析构函数,无论是在程序退出时,还是在调用 dlclose() 时。”请参考 NDK 文件夹(ndk 在您的系统上解压缩并参考 SYSTEM-ISSUES.html)
标签: android android-ndk java-native-interface