C ++从void *转换为SomeClass *

时间:2011-11-29 14:04:58

标签: c++ dynamic-linking dlopen dynamic-library

我正在开发一个C ++库,它将在C ++和C程序中作为插件动态加载(dlopen,dlsym ...)。

C ++程序将使用创建者或库中的驱逐程序函数分别调用构造函数和析构函数。像这样:

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

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

问题是:它不是那种类型的安全。 在这里可以安全吗? (static_castdynamic_castreinterpret_cast ...)

这很重要,因为我打算为每个MyClass方法创建一个C包装器。这将允许我将此库加载到C程序(类似于可以与C风格或C ++风格一起使用的DBus C移植)。 所以我会做这样的事情:

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

请记住,这只是一个虚拟的例子。

非常感谢。

4 个答案:

答案 0 :(得分:1)

不是真的。通过C接口的全部意义在于您消除了对任何C ++ ABI的依赖,因此您无法以“自然”方式保存类型信息。

如果你真的很重要,你可以安装一些复杂的元数据基础设施以允许一些运行时测试,但你肯定不会得到编译时类型 - 安全性。

答案 1 :(得分:1)

您可以使用std::map<void*, MyClass*>。然后,如果指针未被识别,您将获得“在地图中找不到元素”类型的错误而不是未定义的行为。

答案 2 :(得分:0)

您可以通过向C样式结构提供C API指针来获得一些类型安全性,这些结构又包含指向C ++对象的指针。然后你可以更好地控制指针(假设C客户端不会干扰结构内部,它们肯定不应该这样做)并且在C端也有一些类型检查。类似的东西:

struct MyClassHandle {
    void * ptr;
}

然后你非常清楚MyClassHandle内部的ptr会成功转换为MyClass *。

但正如Kerrek SB所说,当你从虚空中施展时,你无法获得任何类型的安全性 - 信息就不存在了。

答案 3 :(得分:0)

你也可以考虑使用句柄(不是指针 - 只是整数)。例如,您可以保存全局数组或将int与指针匹配的映射,并使所有函数仅接受此类句柄,然后使用该全局数组或映射来查找匹配指针。对于数组,句柄只是数组中的索引。