简体   繁体   中英

C++ cast from void* to SomeClass*

I'm working on a C++ library that is going to be dynamic loaded (dlopen, dlsym...) in C++ and C programs as a plugin.

C++ programs will use a creator a destroyer functions from the library to call the constructor and destructor respectively. Something like this:

void *creator(void *instance) {
    return new MyClass();
}

void destroyer(void *instance) {
    MyClass *_instance = static_cast<MyClass*>(instance);
    delete _instance;
}

Problem is: It is not that type safe. Is it possible to be type safe here? ( static_cast , dynamic_cast , reinterpret_cast ...)

This is important, since I intend to create a C wrapper for every MyClass method. That would allow me to load this library into a C program (something like DBus C porting that may be used with C style or C++ style). So I'd do something like this:

int MyClassAddInts(void *instance, int a, int b) {
    MyClass *_instance = static_cast<MyClass*>(instance);
    return _instance->addInts(a, b);
}

Please, keep in mind this is just a dummy example.

Thanks very much.

Not really. The whole point of going through a C interface is that you strip all dependence on any C++ ABI, so there's no way you can preserve type information through that in a "natural" fashion.

f it really matters to you, you could rig up some complicated metadata infrastructure to allow for some runtime tests, but you certainly won't get compile-time type-safety out of this.

You could use a std::map<void*, MyClass*> . Then if the pointer isn't recognized, you'll get a "no element found in map" type of error instead of undefined behavior.

You might be able to get some measure of type safety by giving the C API pointers to C-style structs which in turn contain pointers to your C++ objects. Then you have more control over the pointers (provided C clients don't interfere inside the structs, which they most certainly shouldn't) and there's some type checking on the C side too. Something like:

struct MyClassHandle {
    void * ptr;
}

Then you have a pretty good idea that the ptr from inside a MyClassHandle will cast successfully to MyClass *.

But as Kerrek SB said, you can't get any kind of type safety when you're casting from void * - the information just isn't there.

You might also consider using handles (not pointers - just ints). For example you can hold a global array or a map that matches an int to a pointer, and make all your functions accept only such handles and then use that global array or map to find the matching pointer. In the case of an array the handle would just be an index in the array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM