我想写一个DLL。为了使 DLL 尽可能通用,我决定使用最小的“C”接口和句柄。也就是说,在库本身中,OOP 和 STL 被充分利用,但只导出了使用句柄操作的函数。小例子:
.h 文件
/**
* \brief Хендл ресурса статической геометрии
*/
typedef void* RglGeometryResource;
/**
* \brief Создание ресурса геометрии
* \param vertices Массив исходных вершин
* \param indices Массив индексов
*/
extern "C" RENDERERGL_API RglGeometryResource __cdecl rglCreateGeometryResource(RglVertex* vertices, unsigned vertexCount, unsigned* indices, unsigned indexCount);
/**
* \brief Уничтожение ресурса геометрии
* \param resource Указатель на хендл ресурса
*/
extern "C" RENDERERGL_API void __cdecl rglDestroyGeometryResource(RglGeometryResource* resource);
.cpp 文件
/**
* \brief Создание ресурса геометрии
* \param vertices Массив исходных вершин
* \param indices Массив индексов
*/
RglGeometryResource rglCreateGeometryResource(RglVertex* vertices, unsigned vertexCount, unsigned* indices, unsigned indexCount)
{
auto resource = new GeometryResource(std::vector<RglVertex>(vertices, vertices + vertexCount), std::vector<GLuint>(indices, indices + indexCount));
return reinterpret_cast<RglGeometryResource>(resource);
}
/**
* \brief Уничтожение ресурса геометрии
* \param resource Хендл ресурса
*/
void rglDestroyGeometryResource(RglGeometryResource* resource)
{
GeometryResource* pGeometryResource = reinterpret_cast<GeometryResource*>(*resource);
delete pGeometryResource;
*resource = nullptr;
}
也就是说,在将连接到第三方项目的 .h 文件中,我根本不包含库中存在的必要类,它们仅包含在我执行各种操作的 .cpp 文件中与他们的操作。事实上,我在 OOP C++ 库上得到了类似 C 包装器的东西。
哦,是的,RglVertex示例中点亮的结构是一个完全由普通标准字段(float)组成的结构,所以它在库本身和使用它的应用程序中相同的概率非常高(这就是为什么我在界面和内部都安全地使用它)
结构RglVertex:
struct RglVertex
{
struct { float x; float y; float z; } position;
struct { float r; float g; float b; } color;
struct { float u; float v; } uv;
struct { float x; float y; float z; } normal;
};
一切似乎都合适且有效,但是
我想 - 如果有人删除当前正在使用的资源会发生什么(即提前调用 rglDestroyGeometryResource),我如何在库本身中检查指针不再有效?nullptr,我在删除后分配,因为它分配给一个副本,而不是分配给“在库本身内部”的指针......
问题:
如何使检查库本身中指针的有效性成为可能?什么是最正确的方法?是否有可能在这里以某种方式使用智能指针,它们可以在这种情况下提供帮助(例如,资源创建函数将返回一个智能指针的句柄,而不是资源本身,或类似的东西),还是值得使用一些是完全不同的方法吗?
提前致谢。
“句柄”的概念通常意味着这不仅仅是一个裸指针,而是用于访问某种资源的某种令牌。天真的选项是生成一个随机 id
uintptr_t并将对象存储在 中std::unordered_map<std::uintptr_t, GeometryResource>,并将 id 作为 传递RglGeometryResource。此外,在编写 C 包装器时,允许异常跨越语言边界是非法的。