Исходя из концепции «API как оболочка», сигнатура интерфейсных функций API должна повторять сигнатуру методов интерфейсного класса. Однако здесь мы сталкиваемся с некоторыми проблемами, одна из которых – это обработка ошибок.
В исходной реализации мы обрабатывали ошибки с помощью исключений. Теперь исключения использовать нельзя, в системных API они недопустимы. Тем не менее, вызываемая функция должна как-то уведомить о возникновении ошибки, для чего могут использоваться следующие способы:
1) функция возвращает результат, для которого некоторое предопределенное значение говорит о том, что произошла ошибка. Код ошибки возвращается с помощью отдельного вызова;
2) код ошибки возвращается через дополнительный параметр функции;
3) все функции возвращают результат выполнения, который является кодом ошибки.
Ни один способов не является идеальным, каждый имеет свои достоинства и недостатки. Так, в первом способе возникают сложности, если результат, возвращаемый функцией, не имеет значений, которые недопустимы и могут сигнализировать о возникновении ошибки36. Во втором способе для всех вызовов придется использовать дополнительную переменную – код ошибки, даже если он нас не интересует. В третьем способе, если функция возвращает результат, то для него приходится использовать отдельный входной параметр, что не всегда удобно.
В нашем случае мы выберем третий способ, исходя из следующих соображений: объявления функций будут выглядеть единообразно; возникновение ошибки можно узнать непосредственно в момент вызова, (например, в операторе if); если функция не возвращает значений, то ей не нужно передавать никакие дополнительные параметры. Объявления интерфейсных функций с возвратом ошибок представлены в Листинг 104.
typedef unsigned int ErrorCode;
LIB_API ErrorCode initialize();
LIB_API ErrorCode shutDown();
LIB_API ErrorCode assignDriver(DriverType type);
LIB_API ErrorCode getAssignedDriver(DriverType* type);
LIB_API ErrorCode getSensorDriver(SensorNumber number, DriverType* type);
LIB_API ErrorCode addSensor(SensorType type, SensorNumber number);
LIB_API ErrorCode deleteSensor(SensorNumber number);
LIB_API ErrorCode isSensorExist(SensorNumber number, int* isExist);
LIB_API ErrorCode isSensorOperable(SensorNumber number, int* isOperable);
LIB_API ErrorCode getSensorValue(SensorNumber number, SensorValue* value);
LIB_API ErrorCode querySensorValue(SensorNumber number, SensorValueCallback callback, void* pContextData);
LIB_API ErrorCode readSensorValues(SensorValueCallback callback, void* pContextData);
LIB_API ErrorCode getMinValue(SensorNumber first, SensorNumber last, SensorValue* value);
LIB_API ErrorCode getMaxValue(SensorNumber first, SensorNumber last, SensorValue* value);
LIB_API ErrorCode setAlert(SensorNumber number, SensorAlertCallback callback, SensorValue alertValue, AlertRule alertRule, CheckAlertTimeout checkTimeoutSeс, void* pContextData);
LIB_API ErrorCode resetAlert(SensorNumber number);
LIB_API ErrorCode setSimulateReadCallback(OnSimulateReadValue callback, void* pContextData);
LIB_API ErrorCode setSimulateOperableCallback(OnSimulateOperable callback, void* pContextData);
В реализации этих функций мы будем возвращать код ошибки, получая его из перехваченного исключения. В качестве примера рассмотрим реализацию функции для получения значения датчика (Листинг 105).