0

我正在开发一个 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_cast, dynamic_cast, reinterpret_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

4 回答 4

1

并不真地。通过 C 接口的全部意义在于您剥离了对任何 C++ ABI 的所有依赖,因此您无法以“自然”的方式通过它来保存类型信息。

如果这对你来说真的很重要,你可以构建一些复杂的元数据基础设施来允许一些运行时测试,但你肯定不会从中获得编译时类型安全。

于 2011-11-29T14:18:53.573 回答
1

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

于 2011-11-29T14:22:25.990 回答
0

您可以通过将 C API 指针提供给 C 风格的结构来获得某种类型的安全性,而 C 风格的结构又包含指向 C++ 对象的指针。然后,您可以更好地控制指针(前提是 C 客户端不会干扰结构内部,他们当然不应该这样做),并且 C 端也有一些类型检查。就像是:

struct MyClassHandle {
    void * ptr;
}

然后你有一个很好的想法,来自 MyClassHandle 内部的 ptr 将成功转换为 MyClass *。

但正如 Kerrek SB 所说,当您从 void * 进行转换时,您无法获得任何类型的安全性 - 信息不存在。

于 2011-11-29T14:25:31.780 回答
0

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

于 2011-11-29T14:57:58.347 回答