using ControlPointer = std::unique_ptr
ControlPointer g_SensorControl(sensor::ISensorControl::createControl());
void initialize () // This function is declared in the header file as part of API interface
{
g_SensorControl->initialize();
}
Однако не все так просто, перед нами встают следующие проблемы.
1. В исходной реализации мы использовали специфические типы C++, такие, как std::function, smart pointers и т. п., что не допускается в интерфейсах системных API. Какие типы использовать взамен?
2. Для обработки ошибок в исходной реализации мы использовали исключения. Как сейчас обрабатывать ошибки, ведь в интерфейсах API исключения недопустимы?
3. В исходной реализации мы в каждом потоке могли объявить отдельный интерфейсный класс и работать с ним независимо от остальных потоков. Как теперь обеспечить многопоточную работу, ведь отдельные потоки вызывают одни и те же интерфейсные функции?
4. В исходной реализации драйвер настраивался путем создания нового класса и передаче его в интерфейсный класс. Как теперь настраивать драйвер, если в интерфейсах API нельзя использовать классы?
5. Как организовать обратные вызовы?
Рассмотрим, как эти проблемы можно решить.
6.3.2. Объявления типов
В исходной реализации общие типы объявлены в
#ifdef _WINDOWS // (1)
#ifdef LIB_EXPORTS
#define LIB_API __declspec(dllexport)
#else
#define LIB_API __declspec(dllimport)
#endif
#else
#define LIB_API
#endif
typedef uint32_t SensorNumber; // (2)
typedef double SensorValue; // (3)
typedef uint32_t CheckAlertTimeout; // (4)
typedef uint32_t SensorType; // (5)
typedef uint32_t DriverType; // (6)
typedef uint32_t AlertRule; // (7)
typedef void(*SensorValueCallback)(SensorNumber, SensorValue, void*); // (8)
typedef CheckAlertTimeout(*SensorAlertCallback)(SensorNumber, SensorValue, void*); // (9)
typedef SensorValue(*OnSimulateReadValue)(SensorNumber, int, void*); // (10)
typedef int (*OnSimulateOperable)(SensorNumber, void*); // (11)
enum eSensorType // (12)
{
SENSOR_SPOT = 0,
SENSOR_SMOOTH = 1,
SENSOR_DERIVATIVE = 2,
};
enum eDriverType // (13)
{
DRIVER_SIMULATION = 0,
DRIVER_USB = 1,
DRIVER_ETHERNET = 2
};
enum eAlertRule // (14)
{
ALERT_MORE = 0,
ALERT_LESS = 1
};
В строке 1 объявлены определения для экспортируемых функций. Эти объявления необходимы для компиляции динамической библиотеки в среде Windows, для других платформ они неактуальны.
В строках 2–4 объявлены типы, которые будут использоваться для входных параметров интерфейсных функций. Это те же объявления, которые использовались в исходной реализации (SensorDef.h, см. п. 6.2.2).
В строках 5–7 вместо перечислений C++ объявляются простые числовые типы. В экспортируемых функциях нежелательно использовать перечисления как типы входных параметров, потому что размер этих типов в C явно не определен. Вместо этого перечисления используются в качестве числовые констант, они объявлены соответственно в строках 12–14.
В строках 8–11 объявлены типы указателей на функцию для выполнения обратных вызовов. Как видим, в отличие от исходной реализации здесь присутствует дополнительный параметр для указания контекста вызова.
6.3.3. Интерфейс API и обработка ошибок