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. Как организовать обратные вызовы?

Рассмотрим, как эти проблемы можно решить.

<p>6.3.2. Объявления типов</p>

В исходной реализации общие типы объявлены в SensorDef.h, но мы не можем просто перенести их в интерфейс API из-за использования специфических конструкций С++. Поэтому нам придется повторить эти объявления в стиле C с использованием простых типов, которые можно будет использовать в интерфейсных функциях. Объявления представлены в Листинг 103.

Листинг 103. Объявления типов для интерфейса API (SensorLib.h)

#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 объявлены типы указателей на функцию для выполнения обратных вызовов. Как видим, в отличие от исходной реализации здесь присутствует дополнительный параметр для указания контекста вызова.

<p>6.3.3. Интерфейс API и обработка ошибок</p>
Перейти на страницу:

Похожие книги