Должен ли я использовать целочисленный идентификатор или указатели для моих непрозрачных объектов?

Я пишу уровень абстракции поверх некоторого графического API (DirectX9 и DirectX11), и мне бы хотелось, чтобы вы мнение.

Традиционно я создавал базовый класс для каждой концепции, которую хочу абстрагировать.
В типичном объектно-ориентированном стиле у меня был бы, например, класс Shader и 2 подкласса DX9Shader и DX11Shader.

Я бы повторил процесс для текстур и т. Д. ... и когда мне нужно было их создать, у меня есть абстрактная фабрика, которая вернет соответствующий подкласс в зависимости от текущего графического API.
После RAII возвращаемый указатель будет инкапсулирован в std :: shared_ptr.

Пока все хорошо, но в моем случае есть несколько проблем с этим подходом:

  1. Мне нужно придумать открытый интерфейс, который инкапсулирует функциональность обоих API (и других API в будущем).
  2. Производные классы хранятся в отдельных библиотеках DLL (одна для DX9, одна для DX11 и т. Д.), И наличие shared_ptr для них в клиенте - это проклятие: при выходе графические DLL выгружаются, и если у клиента все еще есть shared_ptr к одному из графических объектов бум , сбой из-за вызова кода из выгруженной DLL.

Это побудило меня изменить свой подход к работе: Я думал, что могу просто вернуть необработанные указатели на ресурсы и очистить графический API после себя, но все еще существует проблема с висячими указателями на сторона клиента и проблема интерфейса. Я даже рассматривал ручной подсчет ссылок, как в COM, но я подумал, что это будет шагом назад (поправьте меня, если я ошибаюсь, из мира shared_ptr ручной подсчет ссылок кажется примитивным) .

Затем я увидел работу Хумуса, в которой все его графические классы представлены целочисленными идентификаторами (очень похоже на то, что делает OpenGL). Создание нового объекта возвращает только его целочисленный идентификатор и сохраняет указатель внутри; все это совершенно непрозрачно!

Классы, представляющие абстракцию (такие как DX9Shader и т. Д.), Все скрыты за API устройства, который является единственным интерфейсом.
Если кто-то хочет установить текстуру, достаточно вызвать device-> SetTexture (ID), а все остальное происходит за кулисами.

Крахом является то, что скрытая часть API раздута, для его работы требуется много стандартного кода, и я не поклонник универсального класса.

Есть идеи / мысли?

5
задан Julien Lebot 30 November 2011 в 09:50
поделиться