Home > database >  C dynamically linked library and void pointer
C dynamically linked library and void pointer

Time:12-22

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);
  • Related