Android – 如何加载共享库?

标签 android android-ndk shared-libraries

我创建了最简单的 EXECUTABLE 和 SHARED_LIBRARY。 不更改 LD_LIBRARY_PATH 就不会加载 SHARED_LIBRARY:

# ./hello
./hello
link_image[1995]: failed to link ./hello
CANNOT LINK EXECUTABLE

# LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./hello
Hello, world!

所有代码如下:

first.h

#ifndef FIRST_H
#define FIRST_H

extern int first(int x, int y);

#endif /* FIRST_H */

first.c

#include "first.h"

int first( int x, int y ) {
    return x + y;
}

你好.c

#include <stdio.h>
#include "first.h"

int main( int argc, char **argv ) {
    printf( "Hello, world!\n" );
    first( 1000, 24 );
    return 0;
}

Android.mk

include $(CLEAR_VARS)
LOCAL_MODULE    := first
LOCAL_SRC_FILES := first.c
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := hello
LOCAL_SRC_FILES := hello.c
LOCAL_SHARED_LIBRARIES := first
LOCAL_LDFLAGS := -Wl,-rpath,. -Wl,-rpath,/data/data/testlib/lib
include $(BUILD_EXECUTABLE)

readelf --all hello

...
Dynamic section at offset 0xef4 contains 25 entries:
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  INTERP         0x000154 0x00008154 0x00008154 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /system/bin/linker]
...
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libfirst.so]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so]
 0x00000001 (NEEDED)                     Shared library: [libm.so]
 0x00000001 (NEEDED)                     Shared library: [libc.so]
 0x00000001 (NEEDED)                     Shared library: [libdl.so]
 0x0000000f (RPATH)                      Library rpath: [.:/data/data/testlib/lib]

RPATH 在这里,但链接器由于某种原因没有使用它。

显然动态链接器在 Android 上工作得很好(使用 LD_LIBRARY_PATH 并且它也没有不同的 RPATH)

我做错了什么?

我是否漏掉了一些明显的东西?

在我的示例中 RPATH 有两个目录,(.:/data/data/teSTLib/lib),一个 (.) 应该足够了。

本例中没有Java。项目不使用也不需要它。

基本上,我正在寻找一种从“我的目录”加载共享库的标准方法,而无需更改 LD_LIBRARY_PATH(有时不可能)或使用包装器 dlopen 所有必需的库。

最佳答案

Bionic 链接器加载器(AOSP 源代码中的 android/bionic/linker/linker.c,如果您想查看)似乎完全忽略了 ELF 中的 RPATH。它只考虑 LD_LIBRARY_PATH 和“/vendor/lib”和“/system/lib”的硬编码数组。

这是基于对我 checkout 的 Ice Cream Sandwich 树上代码的粗略扫描。

这可以解释您所看到的行为。

关于Android – 如何加载共享库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12632762/

相关文章:

java - 使用 Java Toast 调用非静态方法

Android:包括用于不同架构的 ndk .so 库,应用程序崩溃

c - GDB 不从库中加载符号

android - 在 OSX 上构建时,dlib/dlib-android 在运行时崩溃

c - 共享库 : break the ABI compatibility without breaking API compatibility

c - 如何将工作区库添加到 Eclipse CDT autotools C/C++ 项目?

android - 为什么私有(private)集不适用于 MutableLiveData?

android - 如何使用 Google Maps Android App 解决 "An unhandled exception occured"? -Xamarin

linux - GDB:相对于共享库的地址

Android App setContentView(R.layout.activity_main) 与 View 绑定(bind) - 不尊重 layout_gravity