I have two pieces of code: The first, inside a C++ program, is where I load and call a function from an external test_lib.so
:
typedef void *(*init_t)(); // init_t is ptr to fcn returning a void*
typedef void (*work_t)(void *); // work_t is ptr to fcn taking a void*
void *lib = dlopen("test_lib.so", RTLD_NOW);
init_t init_fcn = dlsym(lib, "test_fcn");
work_t work_fcn = dlsym(lib, "work_fcn");
void *data = init_fcn();
work_fcn(data);
The second piece of code is the one that compiles to test_lib.so
:
struct Data {
// ...
};
extern "C" {
void *init_fcn() {
Data *data = new Data; // generate a new Data*...
return data; // ...and return it as void*
}
void work_fcn(void *data) { // take a void*...
static_cast<Data *>(data)->blabla(); // ...and treat it as Data*
static_cast<Data *>(data)->bleble();
}
}
Now, the first piece of code doesn't need to know what Data
is, it just passes the pointer around, so it's a void*
. But the library, which works directly with data
's methods and members, needs to know, so it must convert the void*
s to Data*
s.
But the interface between the two pieces of code is just some functions with pointer arguments and/or return types. I could just keep the void*
in the client, and change every instance of void*
in the library to Data*
. I did that, and everything works fine (my system is Linux/GCC 6.2.1).
My question is: was I lucky, or is this guaranteed to work everywhere? If I'm not mistaken, the result of calling some f(Data*)
with a void*
argument is just as if called reinterpret_cast<Data*>
on the void*
--- and that couldn't possibly be dangerous. Right?
EDIT: No, simply making the Data
type transparent to the client code won't work. The client code calls many libraries through the same API, but each library might have its own implementation. For the client, Data
could be anything.