问题
I have two projects. One of them is Android app with native code, which just loads dynamically library android_lib.so.
Another project is that library (android_lib.so). Code of this library is simple just for learning how things are going. It has only one function. Here is it:
int calculate (int x, int y)
{
return (x*x+y*y);
}
In Makefile I use cross-platform compilator from Android 2.2 toolchains (/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
So I type make and get android_lib.so. In native part of android project (it is mixed Java/C++ Eclipse project) I call 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;
}
}
It succesfully loads android_lib.so. But if I am trying to call function calculate() I get error.
func = (int (*)(int, int)) dlsym( dl_handle, "calculate" );
error = (char *) dlerror();
if (error != NULL) {
__android_log_print(ANDROID_LOG_INFO,"nativeCode",error);
return -3;
}
Function returns -3 and in LogCat of Eclipse I can see
01-01 07:00:44.624: I/nativeCode(8696): Symbol not found:
Please help me to solve this issue.
Update:
$ 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
回答1:
Some important rules:
- you should use
ndk-buildinstead directlyarm-linux-androideabi-gcc - in
Android.mkof library type next options:LOCAL_LDFLAGS += -Wl,--export-dynamic - if
dlerror()returns error it doesn't mean thatdlsym()failed. Check ifdlsym()really returnsNULL. Because it may return a valid address butdlerror()may return error "Symbol not found" at the same time %)) I had this stupid mistake!!! See code. - You do not need call
System.LoadLibrary(your_lib.so). Onlydlopen("your_lib.so")from native code withRTLD_NOWorRTLD_LAZYno matter! Be sure that
your_lib.sois situated in/data/data/app_name/libsfunc = (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; }
That's all :)
来源:https://stackoverflow.com/questions/10785740/dynamic-c-c-lib-for-android-2-2-error-symbol-not-found