tags:

views:

88

answers:

2

Hi, I am loading a DLL from an application and I want the DLL to be able to use a function implemented in the application. The definition of the function is put in a header and is included in the DLL. Can anyone tell me what I am doing wrong here or whether this can't be done? Thanks for any help.

App:

include <API.h>

extern "C" int Mult(int x, int y)
{
    return x*y;
}

int main(int argc, char **argv)
{
if(argc <= 1)
    return -1;

void * pHandle = dlopen(argv[1], RTLD_NOW);
if(pHandle == NULL)
{
    cout << "Can't find DLL : " << argv[1] << endl;
    cout << dlerror() << endl;
    return -2;
}
else
    cout << "DLL Loaded" << endl;

The API.h file:

#ifndef __APP_API__
#define __APP_API__

extern "C" int Mult(int x, int y);

#endif

And the DLL:

#include <API.h>

int Imp1::GetFunctionID()
{
   return Mult(42, 42);
}

When run, this gives me the error:

Can't find DLL : ./ll.d.so ./ll.d.so: undefined symbol: Mult

Please help. Thanks

A: 

You are correct in that it is not possible like that.

It simply does not work that way. DLL dependencies go one way only.

Workarounds are:

  • Place the Mult() function inline in the header
  • use another DLL (or a static lib) which implements the Mult() function
  • configure the DLL for the specific app by setting some global function pointers (or via an interface/abstract class pointer) before calling any "real" function in it (this is rather esoteric for most uses though, except logging and such)
Marcus Lindblom
I cant place Mult function in the header because this is just a test program and in what I am trying to do, I have to have a set of functions that will expose some functionality of a large program to dlls (plugins).
nakiya
I guess I can't use another DLL to implement these functions for the same reason.
nakiya
+2  A: 

You should instruct your compiler to put all the symbols of your executable (App) in it's dynamic symbol table. Otherwise, as Marcus Lindblom said, the dependencies would be one way only. With g++, the option is -rdynamic.

Edgar Bonet
I have compiled my application with -rdynamic.
nakiya
Edgar Bonet
I build from a tool, and it has -fPIC flag on. When I tried to build in your way, I got the error:`/usr/lib64/gcc/x86_64-suse-linux/4.3/../../../../x86_64-suse-linux/bin/ld: /tmp/ccgUhY4M.o: relocation R_X86_64_32 against `__gxx_personality_v0' can not be used when making a shared object; recompile with -fPIC`Does this have anything to do with whats happenning?
nakiya
Again, it still works for me if I replace `-shared` by `-shared -fPIC` on the command I gave you.
Edgar Bonet
Yes it does work for me if i build manually. Are there any flags that can cause problems?
nakiya
This is app build directive: `g++ -ggdb -m64 -D BIG_ENDIAN=1 -Wall -Wshadow -Wpointer-arith -Wcast-qual -D _LARGEFILE_SOURCE -D LITTLE_ENDIAN=0 -D _REENTRANT -rdynamic -fPIC -imacros`
nakiya
Not sure. The important thing is to have `-rdynamic` when compiling the app. Try the command `nm -D app | grep ' T '`: it will list the functions exported by the app and available to the lib. Normally this list is empty unless the app is compiled with `-rdynamic`, in which case you should see your `Mult` function.
Edgar Bonet
I tried your build command. I had to remove `-m64` (I have a 32 bit box) and `-imacros` (which is for include files). I also added `app.cpp -ldl -o app`, obviously. With these amendments it still works for me...
Edgar Bonet
This is funny. I see everything except Mult. 0000000000402573 T OnError0000000000402579 T OnWarning0000000000403068 T _fini0000000000402168 T _init0000000000403058 T naedhsd_dummy`OnError and OnWarning are two functions needed to be implemented due to a lib I have added.
nakiya
Maybe `-rdynamic` is broken in your compiler? You may try `-Wl,--export-dynamic` instead, which should do the same. Check the man pages to see if `-rdynamic` is actually supported by your version of gcc (and `man ld` for `--export-dynamic`).
Edgar Bonet
Oh! I just thought about it! If you are compiling app.cpp into an object file, `-rdynamic` should be used in the link phase: `g++ -rdynamic app.o -ldl -o app`
Edgar Bonet
It works!!! Thanks a heap Edgar Bonet <3. How do you know all these stuff? :D
nakiya
On a side note, why should rdynamic be a linker flag for executable but not dll?
nakiya
@nakiya: `-rdynamic` is implied when compiling a shared object.
caf