Android的NDK - 让两个本机共享库调用对方 [英] Android NDK - make two native shared libraries calling each other

查看:141
本文介绍了Android的NDK - 让两个本机共享库调用对方的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

浪费半天的时间试图建立两个共享库,如: MOD1和MOD2(其中的Andr​​oid NDK编译为libmod1.so和libmod2.so),从源代码中JNI的文件夹和子文件夹,然后让MOD1调用从模2的功能。大量关于如何使构建工作,但运行时动态链接是行不通的答案,应用程序坠毁在启动时。

Wasted half a day trying to build two shared libraries, e.g. mod1 and mod2 (which Android NDK compiles to libmod1.so and libmod2.so), from sources in a jni folder and sub-folders, then have mod1 call a function from mod2. Plenty of answers on how to make the build work, but then runtime dynamic linking was not working, the app crashed on startup.

决定后这个问题,并立刻回答的人,让Q和A的全过程都在一起,并希望别人会不会浪费了一天再研究它。

Decided to post this question and immediately answer it, so that Q and A to the whole process are together, and hopefully someone else won't waste a day researching it again.

格雷格

推荐答案

正确的构建过程是比较容易的,我的问题是,让libmod1.so依赖libmod2.so引起在启动时未满足的链接 - MOD1 code能找不到MOD2共享库,即使两个人在同一个文件夹中的最后一个APK内present,下库/ armeabi,库/ 86等。但是,让我回答完整:

The correct build procedure was relatively easy, my problem was that making libmod1.so dependent on libmod2.so caused unsatisfied links upon startup - mod1 code could not find mod2 shared library, even though both were present within the same folder in the final APK, under libs/armeabi, libs/x86 etc. However, to make my answer complete:

  • 把你的C或C ++在你的Andr​​oid项目下的JNI目录的子目录源和头文件,例如:文件夹MOD1 /和模2 /

  • Put your C or C++ sources and header files under sub-directories of jni dir in your Android project, e.g. folders mod1/ and mod2/

每NDK的说明,创建Application.mk文件,如:我的是:

Per NDK instructions, create Application.mk file, e.g. mine is:

NDK_TOOLCHAIN​​_VERSION = 4.7
  APP_PLATFORM:=机器人-8
  APP_ABI:= armeabi armeabi-V7A 86

NDK_TOOLCHAIN_VERSION=4.7
APP_PLATFORM := android-8
APP_ABI := armeabi armeabi-v7a x86

  • 创建Android.mk下面这个模板:

LOCAL_PATH:= $(叫我-DIR)
  包括$(CLEAR_VARS)
  LOCAL_SHARED_LIBRARIES:= MOD2   #这使得libmod1.so依赖libmod2.so
  LOCAL_MODULE:= MOD1
  LOCAL_SRC_FILES:= MOD1 / file1.c中
  LOCAL_SRC_FILES + = MOD1 / file2.cpp
  ...
  包括$(BUILD_SHARED_LIBRARY)   #这实际上是建立libmod1.so
  
  包括$(CLEAR_VARS)
  LOCAL_MODULE:=模2
  LOCAL_SRC_FILES:=模2 / file1.cc
  LOCAL_SRC_FILES + =模2 / file2.cc
  ...
  包括$(BUILD_SHARED_LIBRARY)   #这个建立libmod2.so

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := mod2    # this makes libmod1.so dependent on libmod2.so
LOCAL_MODULE := mod1
LOCAL_SRC_FILES := mod1/file1.c
LOCAL_SRC_FILES += mod1/file2.cpp
...
include $(BUILD_SHARED_LIBRARY)    # this actually builds libmod1.so

include $(CLEAR_VARS)
LOCAL_MODULE := mod2
LOCAL_SRC_FILES := mod2/file1.cc
LOCAL_SRC_FILES += mod2/file2.cc
...
include $(BUILD_SHARED_LIBRARY)    # this builds libmod2.so

这就是它,都没有建立与ndkbuild脚本出错。你只需要一个C包装从Java调用一些功能。这里是我的问题。因为我只在libmod1.so了可调用的函数从Java,Java中我的C包装类是这样的:

That's about it, all builds without complains with ndkbuild script. You only need a C wrapper to call some functions from Java. And here was my problem. Since I had functions callable from Java only in libmod1.so, my C wrapper class in Java was like:

public class CWrapper {
    static {
        System.loadLibrary("mod1");
    }
    public static native int func1(String aParam);
    ...
}

这似乎是完全合乎逻辑的,我 - 我从Java调用到libmod1.so,所以我用的System.loadLibrary(MOD1),并自libm​​od1.so知道这取决于libmod2.so,并且这两个文件都在同一个文件夹,libmod1会知道如何查找和加载libmod2,对不对?错误!它是在崩溃应用程序启动时以不合适的链接。确切的错误信息是:

This seemed perfectly logical to me - I call to libmod1.so from Java, so I used System.loadLibrary("mod1"), and since libmod1.so knows it depends on libmod2.so, and both files are in the same folder, libmod1 will know how to find and load libmod2, right? Wrong! It was crashing upon app startup with "unsatisfied link". The exact error message was:

java.lang.UnsatisfiedLinkError: Cannot load library: soinfo_link_image(linker.cpp:1635): could not load library "libmod2.so" needed by "libmod1.so"; caused by load_library(linker.cpp:745): library "libmod2.so" not found

我四处寻找一些更多的code添加到Android.mk来解决这个徒劳的。终于找到了!我修改了CWrapper类,如下所示:

I was searching everywhere for some more code to add to Android.mk to resolve this in vain. Finally Eureka! I modified my CWrapper class as follows:

public class CWrapper {
    static {
        System.loadLibrary("mod2"); // must be first, as mod1 depends on mod2!
        System.loadLibrary("mod1");
    }
    public static native int func1(String aParam);
    ...
}

和事情开始工作就像一个魅力...

and things started working like a charm...

格雷格

这篇关于Android的NDK - 让两个本机共享库调用对方的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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