1
votes

I have built my Shared Library using NDK, that has few other libs in it. My lib has few 'extern' function defined. As it is a lib, those 'extern' functions are then declared in project (.cpp) file. I have an issue, where application builds just fine, and crashes on the device with the following error:

07-12 00:45:03.680: E/dalvikvm(2161): dlopen("/data/app-lib/org.libsdl.app-16/libRTEngine.so") failed: dlopen failed: cannot locate symbol "RTEngineSetup" referenced by "libRTEngine.so"...

This RTEngineSetup function is defined in my lib as : extern "C" void RTEngineSetup(); And then my application declares it like: void RTEngineSetup() { ... }

It seems like it can't link them together. This system works just fine on Desktops.

Here is an image of my code design: http://s14.postimg.org/s0r83u801/my_code.png

Here is how I build my libs (first part) and my Application (that includes my libs) (second part): http://ann-tech.com/lib_Android.txt

Please, if anyone has any idea why 'extern' definition () is not linked with it's declaration in application's .cpp file, please let me know. Wasted 2 days now.

Thanks for your time.

2

2 Answers

3
votes

First of all, don't allow LOCAL_ALLOW_UNDEFINED_SYMBOLS in your Android.mk. Then your problem will be visible at link step.

Which .cpp file defines the RTEngineSetup? Does it include the header file that declares it as extern "C"?

In NDK toolchain there is nm utility which can show the list of symbols that are defined in each .so, and also external references.

Unfortunately, the Android dynamic loader cannot resolve circular dependencies. You can split libRTApp in two parts (one which only provides RTEngineSetup() and her kin for libRTEngine.so to link, the other - that depends on RTEngine and all other libs), or use dlsym() in libRTEngine to find the references to RTEngineSetup()` and her kin at run time, e.g.

pRTEngineSetup = dlsym(RTLD_DEFAULT, "RTEngineSetup");

.. and so on

0
votes

Alex!

This is amazing! thank you very much. I am new to NDK and Android coding so had to hack for 3 days straight. When you said to use dlsym(), I had no idea what i it is. But I have figured it out and everything works just perfect now.

Solution: If your Library has C++ functions (defined) as extern - extern void Update(); for example, and you are trying to link this library to your application, where you want to (declare) those functions like that: void Update() { ... }, you have to, in your library C++ code, add this code:

//Library file pointer
void *handle;
handle = dlopen( "lib/libRTApp.so", RTLD_LOCAL | RTLD_LAZY );

// New names for functions you are linking to
void ( *RTUpdate )( void ), ( *RTClose )( void );

// Assigning function to a pointer
*( void ** ) ( &RTUpdate ) = dlsym( handle, "RTAppUpdate" );
*( void ** ) ( &RTClose ) = dlsym( handle, "RTAppClose" );

// Free the memory!
dlclose( handle );  

Thanks a lot Alex Cohn! You have saved me.