Задумал написать DLL. Чтобы DLL была универсальной настолько, насколько это вообще возможно - решил использовать минимальный "C" интерфейс и хендлы. То есть в самой библиотеке у меня по полной используется ООП и 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 файле, где я с ними и произвожу всяческие операции. По сути у меня получается что-то вроде 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, который я присваиваю после delete, он ведь присваивается копии, но не тому указателю, который есть "внутри самой библиотеки"...
Вопрос:
Как сделать так, чтобы в самой библиотеке можно было проверять валидность указателей? Каким будет наиболее правильный подход? Можно ли как-то здесь использовать умные указатели, могут ли они помочь в данной ситуации (например, функция создания ресурса будет возвращать хендл на умный указатель, а не на сам ресурс, или что-то вроде того), или здесь стоит применить какой-то совершенно иной подход?
Заранее спасибо.
Понятие "хэндл" обычно подразумевает, то это не просто голый указатель, а некоторый токен для обращения к какому-то ресурсу. Наивный вариант будет генерировать рандомный id uintptr_t
и хранить объекты в std::unordered_map<std::uintptr_t, GeometryResource>
, отдавая id в качестве RglGeometryResource
.
Кроме того, при написании С врапперов недопустимо позволять исключениям проходить через границу языков.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Всем привет, такой вопрос, я получаю путь к файлу в переменную и далее мне нужно ее использовать для открытия файла, как мне это сделать?
подскажите как проверить наличие ключа в объекте именно на Jquery
Столкнулся с проблемой, при считывании значении элемента выводит undefinedЕсть две кнопки которым на onclick стоит одна функция