views:

696

answers:

2

I have a shim library (shared, C++) which calls functions in another shared library (libexif) and presents a simple interface to C# for Platform Invoke calls. (That is, a C# program uses PInvoke to call my custom shared library which in turn calls another shared library.)

In Windows, my custom shared library links to the shared library when my custom library links and when the C# application executes, all symbols are resolved.

On Linux, linking my shared library does not link the other shared library. With a C++ driver, I specify the other library when the application is linked and at that time, all symbols are resolved. However, when I try to call my shared library from a C# program (compiled using mono) symbols in the other shared library are not resolved. I've tried using the MONO_PATH variable to specify the other library but it seems not to make a difference. I've also tried specifying the unresolved function in a DLLimport statement, but that seems not to help either.

How can I specify a shared library that is not directly called by C# code so that mono/cli finds it at run time?

I use the following commands to build the shared library:

g++ -fPIC -g -c -Wall  libexif-wrapper.cpp
g++ -shared -Wl,-soname,libexif-wrapper.so.1     -o libexif-wrapper.so.1.0.1 libexif-wrapper.o -lc
ar rcs libexif-wrapper.a libexif-wrapper.so.1

And the following command line to compile my C# driver:

mcs -unsafe -define:LINUX Test-libexif-wrapper.cs

On execution I get an error that a symbol used by my shared library is not found:

/usr/bin/cli: symbol lookup error: ../../../C/libexif-wrapper/libexif-wrapper/libexif-wrapper.so.1: undefined symbol: exif_data_new_from_file

(libexif-wrapper is my shared library which serves as a shim between the C# application and libexif.)

I have not been able to figure out how to solve this. Any suggestions would be appreciated.

edit: To answer the question:

Are you sure that the unmanaged libexif-wrapper can be found in the LD_LIBRARY_PATH environment variable?

In fact it is not. I have crafted the path in the DLLImport to point directly to it instead. The run time finds it because it reports the path to it in the error message above. Further the missing symbol is not called by the C# program but rather one of the functions in my shared library calls the function that is then not found. (thanks - hank)

+1  A: 

I'm confused about why you need -lc, but maybe that's a Mono oddity...

Does it work if you add -lexif to the link command? It seems that you're creating a shared library with undefined symbols, but not saying where those symbols should come from. This actually is useful sometimes -- say, creating a plugin that uses a symbol that's expected to be already provided by the application loading it -- but not what you want here; I don't see how libdl (or however Mono loads libraries, maybe it has its own implementation) would know that it needs to load libexif.so for use in your library.

Hopefully you don't have to do something horrible like add libexif.so to the archive...

ephemient
Yes, thanks both. Adding -lexif to link command for my shim library solves the problem.It urns out that -lc is not required. That was part of an example I copied (and I copied it slavishly.) Eliminating it seems to cause no difficulty to either my C++ test application nor my C# test application.
HankB
+1  A: 

You should specify the dependency when you link the wrapper library like

g++ -shared -Wl,-soname,libexif-wrapper.so.1 -o libexif-wrapper.so.1.0.1 libexif-wrapper.o -lc -lexif

When you do that the dynamic linker knows that libexif-wrapper depends on libexif and it can resolve the symbols on load.

lothar