Функции в интерфейсе HIDL сопоставляются с методами в автоматически сгенерированном объявлении класса C++ IFoo. Названия функций в C++ остаются прежними. В следующих разделах описывается, как аргументы и возвращаемые значения HIDL преобразуются в C++.
Параметры функции
Аргументы, перечисленные в файле .hal, сопоставляются с типами данных C++.
Аргументы, которые не относятся к примитивным типам C++, передаются по константной ссылке.
Для каждой функции HIDL, которая возвращает значение (содержит оператор generates), список параметров C++ для этой функции содержит дополнительный аргумент: функцию обратного вызова, которая вызывается со значениями, возвращаемыми функцией HIDL.
Существует одно исключение. Если предложение generates содержит один параметр, который напрямую сопоставляется с примитивом C++, используется пропуск обратного вызова (обратный вызов удаляется, а возвращаемое значение возвращается из функции с помощью обычного оператора return).
Возвращаемые значения функций
Указанные ниже функции возвращают значения.
Ошибки передачи и тип возвращаемого значения
Оператор generates может привести к трем типам сигнатур функций:
- Если функция возвращает только одно значение примитивного типа C++, оно
generatesвозвращается по значению из функции в объектеReturn<T>. - В более сложных случаях возвращаемые значения
generatesпередаются через параметр обратного вызова, указанный в вызове функции, а сама функция возвращает значениеReturn<void>. - Если оператор
generatesотсутствует, функция возвращает значениеReturn<void>.
При вызовах RPC иногда возникают ошибки передачи данных, например когда сервер перестает работать, когда ресурсов передачи данных недостаточно для выполнения вызова или когда переданные параметры не позволяют выполнить вызов (например, отсутствует обязательная функция обратного вызова). Объекты Return хранят признаки ошибок передачи, а также значение T (кроме Return<void>).
Поскольку у клиентской и серверной функций одинаковая сигнатура, серверная функция должна возвращать тип Return, даже если ее реализация не сигнализирует об ошибках передачи. Объекты Return<T> создаются с помощью Return(myTValue) (или могут быть неявно созданы из mTValue, например в операторах return), а объекты Return<void> создаются с помощью Void().
Объекты Return<T> неявно преобразуются в значение T и обратно. Объект Return можно проверить на наличие ошибок передачи, вызвав его метод isOk(). Эта проверка не является обязательной. Однако если произойдет ошибка, которая не будет проверена к моменту уничтожения объекта Return или попытки преобразования значения T, клиентский процесс будет завершен и ошибка будет зарегистрирована. Если isOk() указывает на ошибку передачи данных или сбой вызова из-за логической ошибки в коде разработчика (например, передача nullptr в качестве синхронного обратного вызова), то для объекта Return можно вызвать функцию description(), чтобы вернуть строку, подходящую для регистрации. В таких случаях невозможно определить, сколько кода было выполнено на сервере в результате неудачного вызова. Также предоставляется метод isDeadObject(). Этот метод указывает, что !isOk(), поскольку удаленный объект аварийно завершил работу или больше не существует. isDeadObject() всегда подразумевает !isOk().
Возврат по значению
Если оператор generates сопоставляется с одним примитивом C++, в списке параметров нет параметра обратного вызова. Вместо этого реализация предоставляет возвращаемое значение T в объекте Return<T>, который может быть неявно сгенерирован из примитивного типа T. Пример:
Return<uint32_t> someMethod() { uint32_t return_data = ...; // Compute return_data return return_data; };
Также предоставляется метод Return<*>::withDefault. Этот метод позволяет получить значение, если возвращаемое значение – !isOk().
Этот метод также автоматически помечает возвращаемый объект как нормальный, чтобы клиентский процесс не был завершен.
Возврат с помощью параметра обратного вызова
Обратный вызов может передать возвращаемое значение функции HIDL обратно вызывающей стороне.
Прототип обратного вызова – это объект std::function с параметрами (взятыми из инструкции generates), сопоставленными с типами C++. Возвращаемое значение – void, то есть обратный вызов сам по себе не возвращает значение.
Возвращаемое значение функции C++ с параметром обратного вызова имеет тип Return<void>. Реализация на стороне сервера отвечает только за предоставление возвращаемого значения. Поскольку возвращаемые значения уже передаются с помощью обратного вызова, параметр шаблона T имеет значение void:
Return<void> someMethod(someMethod_cb _cb);
В реализации на стороне сервера из C++ следует возвращать Void() – статическую встроенную функцию, возвращающую объект Return<void>. Пример реализации типичного метода сервера с параметром обратного вызова:
Return<void> someMethod(someMethod_cb _cb) { // Do some processing, then call callback with return data hidl_vec<uint32_t> vec = ... _cb(vec); return Void(); };
Функции без возвращаемых значений
В сигнатуре функции на C++, в которой нет оператора generates, в списке параметров не будет параметра обратного вызова. Тип возвращаемого значения – Return<void>..
Односторонние функции
Функции, помеченные ключевым словом oneway, являются асинхронными (клиенты не будут блокироваться при их выполнении) и не имеют возвращаемых значений. В сигнатуре функции oneway на C++ в списке параметров не будет параметра обратного вызова, а возвращаемое значение на C++ будет Return<void>.