ErrorCode error = ERROR_NO;

  try

  {

    EnumConverter conv;

    conv.convert (driverType, {sensor::DriverType::Simulation, sensor::DriverType::Usb, sensor::DriverType::Ethernet});  // (6)

    if (conv.error())

    {

      return ERROR_INVALID_ARGUMENT;

    }

    switch (conv.result())  // (7)

    {

      case sensor::DriverType::Simulation:

      {

        CreateDriver(sensor::DriverType::Simulation, g_DriverSimulation);

      }

      break;

      case sensor::DriverType::Usb:

      {

        CreateDriver(sensor::DriverType::Usb, g_DriverUSB);

      }

      break;

      case sensor::DriverType::Ethernet:

      {

        CreateDriver(sensor::DriverType::Ethernet, g_DriverEthernet);

      }

      break;

    }

  }

  catch (sensor::sensor_exception& e)

  {

    error = static_cast(e.code());

  }

  return error;

}

В строках 1–3 объявляются указатели для хранения классов всех возможных типов драйверов. В строке 4 объявлена вспомогательная функция для создания драйвера. Эта функция проверяет, создан ли драйвер соответствующего типа, при необходимости создает, инициализирует и передает его в интерфейсный класс.

В строке 5 приведена реализация интерфейсной функции для настройки драйвера. В строке 6 конвертируется переданное числовое значение в перечисление C++ (будет рассмотрено ниже). В строке 7 объявлен оператор switch, в котором анализируется полученное значение перечисления, и вызывается вспомогательная функция с соответствующими параметрами.

В функции API для задания типа драйвера используются числовые значения, а в интерфейсном классе используются перечисления C++. Для того, чтобы сконвертировать числовое значение в перечисление, используется вспомогательный класс EnumConverter (Листинг 109)

Листинг 109. Конвертер числовых значений в перечисление (EnumConverter.h)

template   // (1)

class EnumConverter

{

public:

  template                                     // (2)

  void convert(ConvValueType value, std::initializer_list list)  // (3)

  {

      isError_ = true;

      for (Enum item : list)                              // (4)

      {

          if (static_cast(item) == value)  // (5)

          {

              result_ = item;                             // (6)

              isError_ = false;

              break;

          }

      }

  };

  bool error() const { return isError_; }

  Enum result() const { return result_; }

private:

  bool isError_;

  Enum result_;

};

В строке 1 объявлен шаблонный класс, параметром которого является тип перечисления. Конвертация происходит в функции 2, которая объявлена в виде шаблона, параметром шаблона является тип числового значения для конвертации. Функция принимает число, которое должно быть сконвертировано, а также список значений перечисления (строка 3). Реализация пробегает по всем элементам списка (строка 4) и, если какой-то из элементов списка перечисления равен переданному значению, запоминает это значение перечисления в качестве результата (строки 5,6).

<p>6.3.6. Обратные вызовы</p>

Касательно обратных вызовов мы имеем следующую ситуацию. В системном API контекст вызова передается с помощью указателей на данные, по-другому организация передачи контекста здесь невозможна (см. п. 2.1.2). В интерфейсном классе указатель на данные не используется, поскольку в C++ имеется множество гораздо более изящных способов передачи контекста. Вот тут-то нам и понадобится перенаправление вызовов (см. п. 4.6.2). Реализация одной из интерфейсных функций API, использующей перенаправление вызовов, приведена в Листинг 110.

Листинг 110. Перенаправление вызовов в реализации интерфейсной функции (SensorLib.cpp)

ErrorCode readSensorValues(SensorValueCallback callback, void* pContextData)

{

  ErrorCode error = ERROR_NO;

  try

  {

    using namespace std::placeholders;

    g_SensorControl->readSensorValues(std::bind(callback,_1,_2,pContextData));   // (1)

  }

  catch (sensor::sensor_exception& e)

  {

Перейти на страницу:

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