gpt4 book ai didi

android - 加载依赖于其他共享库的共享库

转载 作者:可可西里 更新时间:2023-11-01 18:55:39 26 4
gpt4 key购买 nike

问题:

我正在 Eclipse 中构建 Android 应用程序,它使用共享库 libgstreamer-0.10.so (为 android-8 平台编译的 GStreamer-android NDK Bundle 库)。我在项目根文件夹中创建了新文件夹 libs/armeabi 并将其放在那里。此外,我已将它附带的所有其他库(其中 158 个)放在同一个文件夹中。如果我把它放在我的主要 Activity 代码中:

static{
System.loadLibrary("gstreamer-0.10");
}

然后在 Android-8 模拟器上构建/安装/运行我的应用程序,它会抛出此错误:

06-15 21:54:00.835: E/AndroidRuntime(402): Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1962]:    33 could not load needed library 'libglib-2.0.so' for 'libgstreamer-0.10.so' (load_library[1104]: Library 'libglib-2.0.so' not found)

现在,libglib-2.0.solibgstreamer-0.10.so 在同一文件夹中,为什么没有加载?我知道链接器试图从 /system/lib 加载它,而 libglib-2.0.so 不存在,但为什么它不从 的位置加载它code>libgstreamer-0.10.so 是?

所以我去发现哪些库 libgstreamer-0.10.so 依赖于这个命令:

arm-linux-androideabi-readelf -d libgstreamer-0.10.so

结果:

Dynamic section at offset 0x118b64 contains 29 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libglib-2.0.so]
0x00000001 (NEEDED) Shared library: [libgobject-2.0.so]
0x00000001 (NEEDED) Shared library: [libgthread-2.0.so]
0x00000001 (NEEDED) Shared library: [libgmodule-2.0.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x0000000e (SONAME) Library soname: [libgstreamer-0.10.so]
0x00000010 (SYMBOLIC) 0x0

前四个libglib-2.0.so、libgobject-2.0.so、libgthread-2.0.so、libgmodule-2.0.so都位于同一个文件夹libgstreamer-0.10.so 位于设备上的 (/data/data/com.marko.gstreamer_test/lib) 中。

逻辑解决方案:

因此,我尝试在加载 libgstreamer-0.10.so 之前加载这四个库,并且成功了:

static{
System.loadLibrary("glib-2.0");
System.loadLibrary("gthread-2.0");
System.loadLibrary("gobject-2.0");
System.loadLibrary("gmodule-2.0");
System.loadLibrary("gstreamer-0.10");
}

我的问题是:

  1. 我能否以某种方式告诉链接器也从应用程序位置加载库?比如将路径添加到某些环境变量或其他东西...类似于 Linux 上的 PATH。

  2. 我的解决方案是否有不良副作用?我的意思是,链接器在加载 libgstreamer-0.10.so 之前也会这样做。但这会带来什么问题吗?

  3. 我可以将我的库安装到没有开启Root的设备上的 /system/lib 文件夹吗?

最佳答案

根据 https://groups.google.com/forum/?fromgroups#!msg/android-ndk/J3lzK4X--bM/4YaijymZy_AJ

Yes, and this is the documented behaviour: you must load libraries in reverse dependency order explicitely. [...] It is a limitation of the system.

In a nutshell, the dynamic linker doesn't know anything about your application (e.g. where its libraries live), it only knows about the LD_LIBRARY_PATH value that was set when the process was created. When you start an Android application, you really fork the Zygote process, you don't create a new one, so the library search path is the initial one and doesn't include your app's /data/data//lib/ directory, where your native libraries live. This means that dlopen("libfoo.so") will not work, because only /system/lib/libfoo.so will be searched.

When you call System.loadLibrary("foo") from Java, the VM framework knows the application's directory, so it can translate "foo" into "/data/data//lib/libfoo.so", then call dlopen() with this full path, which will work.

It libfoo.so references "libbar.so", then the dynamic linker will not be able to find the latter.

Add to this that even if you update LD_LIBRARY_PATH from native code, the dynamic linker will not see the new value. For various low-level reasons, the dynamic linker contains its own copy of the program's environment as it was when the process was created (not forked). And there is simply no way to update it from native code. This is by design, and changing this would have drastic security constraints. For the record, this is also how the Linux dynamic linker works, this forces any program that needs a custom library search path to use a wrapper script to launch its executable (e.g. Firefox, Chrome and many others).

我已经给作者发邮件询问这是在哪里记录的。

Tor Lillqvist 继续提供解决方法:https://groups.google.com/d/msg/android-ndk/J3lzK4X--bM/n2zUancIFUEJ

To be more verbose, what that lo_dlopen() function does is:

  • Searches where the shared object in question is. It searches a set of directories passed to it by the Java code. The Java code looks at LD_LIBRARY_PATH and adds the app's lib directory to that.
  • Opens the found shared object file and reads the ELF structures in it . Not all, but just enough to find out what shared objects it needs (the DT_NEEDED ones as displayed by arm-linux-androideabi-readelf -d). It calls itself recursively on the needed shared objects.
  • Only after that, i.e. after making sure that all needed other shared objects have been loaded, it calls the real dlopen() on the found full pathname to the shared object.

您可以在 http://cgit.freedesktop.org/libreoffice/core/tree/sal/android/lo-bootstrap.c?id=5510127e89d6971a219ce3664e4631d6c6dda2b1 找到他的代码

更新:根据http://code.google.com/p/android/issues/detail?id=34416截至 2012 年 12 月,此代码已集成到 Android 中。耶!为 API 级别 18 及更高级别的设备自动加载依赖项。如果您支持旧的 API 级别,您仍然需要列出依赖项。

关于android - 加载依赖于其他共享库的共享库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11058898/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com