【问题标题】:Dynamic C/C++ lib for Android 2.2: error Symbol not found适用于 Android 2.2 的动态 C/C++ 库:找不到错误符号
【发布时间】:2012-05-28 13:49:25
【问题描述】:

我有两个项目。其中之一是带有本机代码的 Android 应用程序,它只是动态加载库 android_lib.so。

另一个项目是那个库 (android_lib.so)。这个库的代码很简单,只是为了了解事情的进展。它只有一个功能。就是这样:

int calculate (int x, int y)
{
  return (x*x+y*y);
}

Makefile 我使用来自 Android 2.2 工具链的跨平台编译器 (/usr/local/android-ndk-r8/toolchains/arm-linux-androideabi4.4.3/prebuilt/linux-x86/ bin/arm-linux-androideabi-gcc):

NDK_DIR=/usr/local/android-ndk-r8/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin
ANDROID_GCC=$(NDK_DIR)/arm-linux-androideabi-gcc
NDK_ROOT=/usr/local/android-ndk-r8

CPPFLAGS = $(NDK_ROOT)/platforms/android-8/arch-arm/usr/include
CFLAGS =-nostdlib
LDFLAGS = -Wl,-rpath-link=$(NDK_ROOT)/platforms/android-8/arch-arm/usr/lib/ -L$(NDK_ROOT)/platforms/android-8/arch-arm/usr/lib/
LIBS=-lc

android_lib.so: calculate.o
    $(ANDROID_GCC) $(CFLAGS)  -shared -o android_lib.so calculate.o 

calculate.o: calculate.c
    $(ANDROID_GCC) $(CPPFLAGS) $(CFLAGS) -c -fPIC calculate.c
clean:
    rm -f *.o *.so 

所以我输入 make 并得到 android_lib.so。 在 android 项目的本机部分(它是混合 Java/C++ Eclipse 项目)我调用 dlopen()

dl_handle = dlopen( lib, RTLD_LAZY );
  if (!dl_handle) {
      error = (char *) dlerror();
      if (error != NULL) {
          __android_log_print(ANDROID_LOG_INFO,"nativeCode",error);
          return -1;
      }
      else {
          sprintf(sError,"%s is not found",lib);
          __android_log_print(ANDROID_LOG_INFO,"nativeCode",sError);
          return -2;
      }
  }

它成功加载了android_lib.so。但是如果我试图调用函数 calculate() 我会得到错误。

func = (int (*)(int, int)) dlsym( dl_handle, "calculate" );
  error = (char *) dlerror();
  if (error != NULL) {
      __android_log_print(ANDROID_LOG_INFO,"nativeCode",error);
      return -3;
  }

函数返回 -3 并且在 Eclipse 的 LogCat 中我可以看到

01-01 07:00:44.624: I/nativeCode(8696): Symbol not found:

请帮我解决这个问题。

更新

$ cd /usr/local/android-ndk-r8/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin 
$ sudo ./arm-linux-androideabi-objdump -T /home/chet/workspace/dinLib/android_lib.so

/home/chet/workspace/dinLib/android_lib.so:     file format elf32-littlearm

DYNAMIC SYMBOL TABLE:
00000234 l    d  .text  00000000 .text
00000274 g    D  *ABS*  00000000 __exidx_end
000012e0 g    D  *ABS*  00000000 _bss_end__
00000234 g    DF .text  00000040 calculate
000012e0 g    D  *ABS*  00000000 __bss_start__
00000274 g    D  *ABS*  00000000 __exidx_start
000012e0 g    D  *ABS*  00000000 __bss_end__
000012e0 g    D  *ABS*  00000000 __bss_start
000012e0 g    D  *ABS*  00000000 __end__
000012e0 g    D  *ABS*  00000000 _edata
000012e0 g    D  *ABS*  00000000 _end
000012e0 g    D  .got   00000000 __data_start

【问题讨论】:

  • 你能显示“arm-linux-androideabi-objdump.exe -T android_lib.so”的输出吗(看看库是否有“计算”符号)?另外-您是否尝试过使用 ndk-build 而不是手动调用 gcc 来构建共​​享库?这行得通吗?
  • @Mārtiņš Možeiko 我已经用这个工具的输出更新了我的帖子。我会尝试 ndk-build。谢谢!
  • @Mārtiņš Možeiko 我已经使用 ndk-build 编译了库。我再次收到该错误(
  • 你把这个 android_lib.so 文件放在设备的什么地方?你是从 Java 调用 System.loadLibrary("android_lib.so") 吗?
  • android_lib.so 位于 /data/data//lib 我正在使用 dlopen() 加载它。之后,我用 dlsym() 调用函数。上面我的问题帖子中有代码。

标签: android dynamic makefile android-ndk


【解决方案1】:

一些重要的规则:

  1. 你应该直接使用ndk-build 而不是arm-linux-androideabi-gcc
  2. 在库类型的Android.mk 中下一个选项:LOCAL_LDFLAGS += -Wl,--export-dynamic
  3. 如果dlerror() 返回错误并不意味着dlsym() 失败。检查dlsym() 是否真的返回NULL。因为它可能会返回一个有效的地址,但dlerror() 可能会同时返回错误“找不到符号”%))我犯了这个愚蠢的错误!见代码。
  4. 您无需致电System.LoadLibrary(your_lib.so)。仅来自本机代码的 dlopen("your_lib.so")RTLD_NOWRTLD_LAZY 无论如何!
  5. 确保your_lib.so 位于/data/data/app_name/libs

    func = (int (*)(int, int)) dlsym( dl_handle, "calculate" );
    error = (char *) dlerror();
    if (error != NULL) { //replace it with if ((func == NULL)&& (error != NULL))
      __android_log_print(ANDROID_LOG_INFO,"nativeCode",error);
      return -3; 
    }
    

就是这样:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-09
    • 2012-01-27
    相关资源
    最近更新 更多