On Aug 21, 2012, at 9:46 PM, AlexGray <alexjgra...@gmail.com> wrote:
> I think the key line is this one 
> 
> 08-22 12:56:59.220 D/Mono    (10563): DllImport error loading library: 
> 'Cannot load library: link_image[1941]:   140 could not load needed library 
> 'libQCAR.so' for 'libQCARWrapper.so' (load_library[1096]: Library 
> 'libQCAR.so' not found)'.
> 
> But i can't figure out why it cannot load libQCAR.so, as that is definately 
> in the apk, in the same place as libQCARWrapper.so. So I would assume if it 
> can find one, it can find the other.

You would think so, and you would be wrong.

Here's the problem: Android doesn't set LD_LIBRARY_PATH after the process is 
forked, and thus ld.so doesn't know to check the 
/data/data/your.package.name/lib directory; everything passed to dlopen() is 
fully qualified.

Result: you have libQCARWrapper.so which has a link-time dependency on 
libQCAR.so, but when you load libQCARWrapper.so dlopen(3) doesn't know to check 
your app's lib directory to find libQCAR.so, so it fails the load.

What's the fix?

        
https://groups.google.com/forum/?fromgroups=#!topic/android-ndk/J3lzK4X--bM
> Yes, and this is the documented behaviour: you must load libraries in reverse 
> dependency order explicitely. [0]

As the note says, you need to do one of two things:

(1) Find a "safe" function in libQCAR.so that you can P/Invoke AND INVOKE 
before you call your libQCARWrapper.so function. When you invoke the libQCAR.so 
function, libQCAR.so will be loaded, allowing your libQCARWrapper.so function 
invocation to work.

(2) P/Invoke to dlopen(3) and explicitly dlopen("path/to/libQCAR.so"). The 
downside is that you'll need to know what "path/to" is; given that anyone (and 
everyone!) can modify Android, it's safest to use the 
ApplicationInfo.NativeLibraryDir property [2]. The problem is that 
ApplicationInfo.NativeLibraryDir was added in API9, so if you want to target 
anything older you'll need to assume something; Mono for Android assumes that 
native libraries are stored in Path.Combine(ApplicationInfo.DataDir, "lib") 
(see e.g. the generated obj\Debug\android\src\mono\MonoPackageManager.java).

Of course, both approaches require that your native libraries have no circular 
dependencies, as there's no way to individually load libraries if they have a 
circular link-time dependency...

Finally, do note the cautionary note at the end of the above android-ndk forum 
message:

> Some people have been playing with rpath to embed the full path of dependent 
> libraries in the .so itself, but this is no[t] guaranteed to work (e.g. it 
> will break if you move the app to the SD Card, because now the libraries are 
> in a directory with a completely different path, most of it random iirc).

 - Jon

[0] Though I do wish I knew _where_ this was "documented behavior", as [1] 
doesn't find anything meaningful...

[1] https://www.google.com/search?q=dlopen+site%3Adeveloper.android.com

[2] 
http://androidapi.xamarin.com/?link=P:Android.Content.PM.ApplicationInfo.NativeLibraryDir

_______________________________________________
Monodroid mailing list
Monodroid@lists.ximian.com

UNSUBSCRIBE INFORMATION:
http://lists.ximian.com/mailman/listinfo/monodroid

Reply via email to