Как абстрагировать ваш код от заголовочного файла для конкретной платформы - PullRequest
1 голос
/ 24 февраля 2012

Привет. Я пытаюсь найти способ предотвратить включение заголовочного файла для конкретной платформы, например, windows.h. Любопытно, что ни одно из найденных мной решений не является удовлетворительным для меня. Может быть, это не может быть достигнуто.

Я думаю, что для достижения этой цели необходимо использовать несколько методов. И в интернете много примеров, но я не смог найти ни одного из аспектов. Что-то должно говорить / создавать в вашей абстракции. Вот пример:

Это действительно упрощенная версия цели рендеринга окна рендеринга.

//D3D11RenderWindow.h
#include <d3d11.h>
class D3D11RenderWindow: public GfxRenderWindow
{
public:
    bool initialize(HWND windowHandle);

private:
    HWND windowHandle_; /// Win32 window handle
};  

Это не такая большая проблема, это код для конкретной платформы, который включается только кодом для конкретной платформы. Но нам нужно на самом деле создать экземпляр этого типа, чтобы «точка входа» тоже знала о коде, специфичном для платформы.

Например, заводской класс:

//GfxRenderWindowFactory.h
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>

class GfxRenderWindow;

class GfxRenderWindowFactory
{
public:
    static std::unique_ptr<GfxRenderWindow> make(HWND windowHandle);
};

Теперь этот фабричный класс должен быть включен "клиентом" библиотеки (здесь - рендерером). Что мне не нравится, так это #include "windows.h", потому что он слишком подвержен ошибкам, у всех, кто его включит, даже если он им не нужен, будет весь мир и окна .... Прекомпиляция заголовок не является решением, потому что теперь компилятор принудительно включает его в cpp (это ценный инструмент для ускорения времени компиляции, но не инструмент для отделения кода, специфичного для платформы, от переносимого кода)

Я подумал о том, чтобы поместить #include в cpp перед включением его заголовка, а не в файл заголовка, например так:

//GfxRenderWindowFactory.cpp
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include "GfxRenderWindowFactory.h"

/// Implementation of GfxRenderWindowFactory goed here ....

Таким образом, это заставит любого, кто хочет использовать этот класс, включить заголовок, относящийся к конкретной платформе, и он будет в лучшем положении, чтобы судить, включают ли он этот заголовок в плохом месте, как в одном из своих собственных файлов заголовков. 1018 *

Каково ваше решение для этого? Что вы думаете о моем решении? Безумно?

Я хочу отметить, что для меня крайне важно делать переносимый код правильно! Отвечайте так же, как просто включите windows.h и не волнуйтесь об этом, это не правильный ответ. Для меня это не очень хорошая практика кодирования.

Надеюсь, я прояснил свой вопрос. Если не скажи мне, я уточню

Большое спасибо!

## Редактировать ## Из небольшого разговора с hmjd я хотел бы сохранить включение windows.h в заголовочный файл, поскольку, я согласен, это делает его более удобным для использования. Поэтому было бы неплохо иметь способ предотвратить включение в заголовочный файл, и таким образом обеспечить, чтобы файл мог быть включен только в cpp. Это возможно?

Ответы [ 3 ]

1 голос
/ 24 февраля 2012

Поскольку основная проблема передает HWND в GfxRenderWindowFactory::make, GfxRenderWindowFactory::make не следует принимать HWND.

1 голос
/ 24 февраля 2012

Использование предопределенного макроса, такого как WIN32, или макроса, определенного вашей системой сборки, недостаточно:

#ifdef WIN32
#include <windows.h>
#else
include other platform specific headers
#endif

Это общий подход (и FWIW единственный подход, который я когда-либо использовал).

0 голосов
/ 08 марта 2014

Привет, я работал над кросс-платформенным API GUI wxsmith. Первое, что вам нужно сделать, это создать классы своими собственными ручками. Дескриптор 1 из 3 вещей:

  1. Пустота *.
  2. Класс *.
  3. Структура *.

Используйте такую ​​функцию:

#define create_handle(handle) struct __##handle{unsigned int unused;}; typedef __##handle *##handle;

Затем вызовите эту функцию, и она создаст структуру и указатель на структуру. Указатель - это ручка. Затем приведите к тому, что вы хотите reinterpret_cast (ваш дескриптор здесь); и когда все готово, вы можете разыграть это в своих объектных файлах, библиотеках или библиотеках. И сделайте глобальное определение для своего дескриптора окна, исследуйте, как другие ОС делают это, и вы сделали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...