PDA

View Full Version : Dynamic loading with C++



karas
12-23-2006, 04:34 AM
I have problem with dynamic loading function with C++ (in C it works).
Let test.cpp be


#include <iostream>
#include <string>

using namespace std;

void f(string s)
{
cout << s << endl;
}

and main.cpp


#include <dlfcn.h>
#include <string>

using namespace std;

extern "C" void f(string);

int main()
{
void* handle = dlopen("libtest.so", RTLD_LAZY);
void (*test)(string) = dlsym(handle, "f");
(*test)("Hello, World!");
dlclose(handle);
}

Then, I made libtest.so with


g++ -c test.c
g++ -shared -fPIC -o libtest.so test.o

put it into /usr/lib and set appropriate file attributes. But,


g++ -ldl main.cpp

gives error main.cpp:12: error: invalid conversion from `void*' to `void (*)(std::string)'.
Why? Same thing works in C with char* and printf() instead of string and cout.

vart
12-23-2006, 04:42 AM
have you tried to cast the pointer returned by the dlsym function to the proper type of the pointer?

karas
12-23-2006, 07:48 AM
If I cast it with


void (*test)(string) = (void (*)(string))dlsym(handle, "f");

then it compiles but on run gives Segmentation fault.

ZuK
12-24-2006, 05:10 AM
Trouble is the namemangling.
have a look in the library how the function is actually called. ( use nm ).
Guess there should be a better way.
Got this to run:
the lib

#include <iostream>
#include <string>

using namespace std;

void testfunc(string s)
{
cout << s << endl;
}


#include <dlfcn.h>
#include <string>
#include <iostream>

using namespace std;

typedef void (*test)(string);

int main()
{
void* handle = dlopen("libtest.so", RTLD_LAZY);
if ( 0 == handle ) {
cout << "failed to load 'libtest.so'." << endl;
exit(1);
}

test t = (test)dlsym(handle, "_Z8testfuncSs");
if ( 0 == t ) {
cout << "failed to load 'testfunc()'." << endl;
exit(1);
}
t("Hello, World!");
dlclose(handle);
}

Kurt

ZuK
12-24-2006, 05:39 AM
After some experimenting I think the easiest way is to declare the exported function in the dynamic libarary as extern "C", and use it as extern "C" as well. This way there are no namemangling issues.
Kurt

CornedBee
12-24-2006, 05:57 AM
There is still one other issue: dlsym() returns a void*, and conversions between object- and function-pointers are absolutely invalid in C++. (GCC allows them, but it will issue a warning on most levels.)

See here:
http://www.trilithium.com/johan/2004/12/problem-with-dlsym/

vart
12-24-2006, 07:40 AM
To prevent SegFault - just check the returned pointer before use

karas
12-25-2006, 02:13 AM
extern declaration must be placed into f's definition in the test.cpp and removed from main.cpp.
Thanks for the help, especially for the URL about pointer conversions.