I'm in the following situation: I'm writing a C program which has to dynamically load a C library (i.e. via dlopen
and friends in Linux and LoadLibrary
and friends in Windows). This can be done creating a C interface.
Now, both in the program and in the library I manage some object which has some specified template members and some methods:
struct MyObject {
std::vector<int> _vec;
//...
void do_something();
};
Now, if the library would have loaded statically I would have written a library function such as
void some_function(MyObject& o);
but since it is dynamically loaded I need some other signature. I was thinking the following: a common header like
//interface.hpp
extern "C" {
void ob_w(void*);
}
struct MyObject {
//...
}
Then, on the library side
//lib.cpp
#include "interface.hpp"
void ob_w(void* ptr)
{
MyObject* p = (MyObject*)ptr;
p->do_something();
}
and, for the main program
//main.cpp
#include "interface.hpp"
int main()
{
void* handle = nullptr;
void (*fptr)(void*);
handle = dlopen(...)
fptr = dlsym(...)
MyObject foo;
fptr((void*)&foo);
//...
}
Looking around I found other similar questions, but in all of them the library was written in C and so different solution were adopted. Here both library and program are written in C and the void pointer is there just to avoid some adaptors. I would like to know whether my approach is correct (I tried on a linux machine and seems go give the correct result) and safe. In the case it is not, how could I pass the pointer of the object without introducing any overhead (for instance of some adaptor)?
CodePudding user response:
Hoisting my comment into an answer: you definitely don’t need to change the signature of your function to make it work with dynamic linking, if you’re happy to require C . That is, the following works:
extern "C" void some_function(MyObject& o) {
o.do_something();
}
And then you could have a main.cpp
as follows (fragment):
void* lib = dlopen("myobject.so", RTLD_LAZY);
if (not lib) fail_spectacularly();
void (*some_function)(MyObject&) = reinterpret_cast<decltype(some_function)>(dlsym(lib, "some_function"));
if (not some_function) fail_spectacularly();
MyObject obj = whatever;
some_function(obj);