【问题标题】:Error during Cross-compiling C code with Dynamic libraries使用动态库交叉编译 C 代码时出错
【发布时间】:2013-02-03 01:10:23
【问题描述】:

我有两个文件:

lib.c

#include<stdio.h>

void hi() {
  printf("Hi i'm a library function in lib.so\n");
} 

和main.c

#include<stdio.h>
#include<dlfcn.h>
/* based on Jeff Scudder's code */
int main() {
  void *SharedObjectFile;
  void (*hi)();

  // Load the shared libary;
  SharedObjectFile = dlopen("./lib.so", RTLD_LAZY);

  // Obtain the address of a function in the shared library.
  ciao = dlsym(SharedObjectFile, "hi");

  // Use the dynamically loaded function.
  (*hi)();

  dlclose(SharedObjectFile);
}

我尝试使用以下命令构建可执行文件:

导出 LD_LIBRARY_PATH=pwd

gcc -c -fpic lib.c

gcc -shared -lc -o lib.so lib.o

gcc main.c -ldl

而且效果很好。 然后我尝试使用以下命令在 Android(Nexus One,带有 ARM-v7-0a 架构)上导出我的程序:

导出 LD_LIBRARY_PATH=pwd

arm-none-linux-gnueabi-gcc -c -fpic lib.c

arm-none-linux-gnueabi-gcc -shared -lc -o lib.so lib.o

arm-none-linux-gnueabi-gcc main.c -ldl -o main

adb push main /system/app

在我智能手机的正确文件夹上执行 ./main 的结果是:

./main: 未找到

即使我的文件就在那里!

在交叉编译过程中我是否遗漏了什么?有什么帮助吗? 我正在使用来自 CodeSourcery 的交叉编译器,它适用于没有 .so 库的静态程序。 谢谢

编辑:正如 Igor 下面所说,这是一个链接器问题。此命令修复它:

arm-none-linux-gnueabi-gcc -o test main.c -Wl,--dynamic-linker=/system/bin/linker -ldl

就我而言,我需要其他库,因为在 /system/lib/ 中没有很多 .so 文件。

【问题讨论】:

  • 您不使用 NDK 的任何特殊原因?
  • C 代码在安卓设备上执行后是否无法在其文件夹中找到 .so?我知道程序应该在同一个文件夹中检查 .so 库文件 /usr/lib 或 /usr/local/lib 但我的设备上没有后两者
  • main添加错误检查和dlerror调用怎么样?
  • @Michael:我不能使用 NDK,我应该使用命令行通过单个交叉编译器调用来实现此类代码的执行。
  • 由于"./lib.so" 包含一个斜杠,dlopen 应该只尝试该文件名,所有关于LD_LIBRARY_PATH 和/usr/lib 的内容都不应该适用。

标签: android c arm cross-compiling codesourcery


【解决方案1】:

“未找到”消息不是指共享对象,而是指动态链接器。 Linux 使用/lib/ld-linux.so.2(或/lib64/ld-linux-x86-64.so.2 用于x64),而Android 使用/bin/linker。您可以使用readelf -l 检查您的程序使用的动态加载器,例如:

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x08048034 0x08048034 0x00100 0x00100 R E 0x4
  INTERP         0x000134 0x08048134 0x08048134 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]

您可以指定与 ld 的 --dynamic-linker 开关一起使用的链接器,但可能存在其他差异。例如,Android 使用称为仿生的精简 libc 实现,它可能缺少您的程序所依赖的功能,或者具有不同的行为。

在为 Android 编译程序时,您应该使用 NDK 或其他针对 Android 的工具链。即使它是基于 Linux 内核的,但差异也足够大,以 Linux 为目标的工具链是不够的。

【讨论】:

  • 谢谢伊戈尔!这就是我正在寻找的解释。我的问题确实与链接器有关,因为如果我在我的 main 上使用 readelf -l,它会显示“/lib/ld-linux ....”,所以它是一个错误的链接器。既然我知道这是一个链接问题,我正在寻找更多处理这个问题的线程。我只需要正确使用 arm-none-linux-gnueabi-ld 就可以了。
猜你喜欢
  • 2015-12-17
  • 1970-01-01
  • 2016-12-15
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-22
相关资源
最近更新 更多