1

私は2つのプロジェクトを持っています。それらの 1 つは、ライブラリ android_lib.so を動的にロードするだけのネイティブ コードを含む Android アプリです。

別のプロジェクトはそのライブラリ (android_lib.so) です。このライブラリのコードは、物事がどのように進んでいるかを知るためだけに単純です。機能は 1 つだけです。はい、これ:

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
4

1 に答える 1

3

いくつかの重要なルール:

  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_NOWまたはRTLD_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; 
    }
    

それで全部です :)

于 2012-05-30T14:32:51.640 に答える