Las funciones de una interfaz HIDL se asignan a métodos en la declaración de clase C++ IFoo
generada automáticamente. El nombre de cada función sigue siendo el mismo en C++; en las siguientes secciones, se describe cómo se traducen los argumentos y los valores de retorno de HIDL a C++.
Parámetros de la función
Los argumentos que se enumeran en el archivo .hal
se asignan a tipos de datos de C++.
Los argumentos que no se asignan a un tipo C++ primitivo se pasan por referencia const.
Para cada función HIDL que tiene un valor que se muestra (tiene una sentencia generates
), la lista de parámetros de C++ para esa función tiene un argumento adicional: una función de devolución de llamada a la que se llama con los valores que se muestran de la función HIDL.
Hay una excepción: Si la cláusula generates
contiene un solo parámetro que se asigna directamente a una primitiva de C++, se usa la eliisión de devolución de llamada (se quita la devolución de llamada y se muestra el valor que se muestra desde la función a través de una sentencia return
normal).
Valores que devuelven las funciones
Las siguientes funciones tienen valores que se muestran.
Errores de transporte y tipo de devolución
La sentencia generates
puede generar tres tipos de firmas de función:
- Para un solo valor que sea una primitiva de C++, el valor que se muestra de
generates
se muestra por valor de la función en un objetoReturn<T>
. - En casos más complejos, los valores que muestra
generates
se muestran a través del parámetro de devolución de llamada proporcionado con la llamada a la función, y la función muestraReturn<void>
. - Cuando no existe una sentencia
generates
, la función muestraReturn<void>
.
En ocasiones, las llamadas a RPC pueden encontrar errores de transporte, p.ej., cuando falla el servidor, cuando los recursos de transporte no son suficientes para completar la llamada o cuando los parámetros pasados no permiten completar la llamada (por ejemplo, falta una función de devolución de llamada obligatoria). Los objetos Return
almacenan indicaciones de errores de transporte, así como un valor T
(excepto Return<void>
).
Como las funciones del cliente y del servidor tienen la misma firma, la función del servidor debe mostrar un tipo Return
, aunque su implementación no indique errores de transporte. Los objetos Return<T>
se construyen con Return(myTValue)
(o se pueden construir de forma implícita a partir de mTValue
, como en las sentencias return
) y los objetos Return<void>
se construyen con Void()
.
Los objetos Return<T>
tienen una conversión implícita hacia y desde su valor T
. Para verificar si el objeto Return
tiene errores de transporte, llama a su método isOk()
. Esta verificación no es obligatoria. Sin embargo, si se produce un error y no se verifica cuando se destruye el objeto Return
o se intenta una conversión de valor T
, se finalizará el proceso del cliente y se registrará un error. Si
isOk()
indica un error de transporte o una falla de llamada debido a un error de
lógica en el código del desarrollador (como pasar nullptr
como una devolución de llamada
síncrona), se puede llamar a description()
en el objeto Return para
mostrar una cadena adecuada para el registro. En esos casos, no hay forma de determinar cuánto código se pudo haber ejecutado en el servidor como resultado de la llamada fallida. También se proporciona el método isDeadObject()
. Este método indica que !isOk()
se debe a que el objeto remoto falló o ya no existe. isDeadObject()
siempre implica !isOk()
.
Mostrar por valor
Si la sentencia generates
se asigna a una sola primitiva de C++, no hay ningún parámetro de devolución de llamada en la lista de parámetros. En su lugar, una implementación proporciona el valor que se muestra T
en un objeto Return<T>
, que se puede generar de forma implícita a partir del tipo primitivo T
. Por ejemplo:
Return<uint32_t> someMethod() { uint32_t return_data = ...; // Compute return_data return return_data; };
También se proporciona el método Return<*>::withDefault
. Este método proporciona un valor en los casos en que el valor que se muestra es !isOk()
.
Este método también marca automáticamente el objeto que se muestra como correcto para que no se cancele el proceso del cliente.
Cómo mostrar un resultado con el parámetro de devolución de llamada
Una devolución de llamada puede pasar el valor de retorno de la función HIDL al llamador.
El prototipo de la devolución de llamada es un objeto std::function
con parámetros (tomados de la sentencia generates
) asignados a tipos de C++. Su valor que se muestra es nulo; la devolución de llamada en sí no muestra ningún valor.
El valor que se muestra de una función de C++ con un parámetro de devolución de llamada tiene el tipo Return<void>
. La implementación del servidor solo es responsable de proporcionar el valor que se muestra. Como los valores que se muestran ya se transfieren con la devolución de llamada, el parámetro de plantilla T
es void
:
Return<void> someMethod(someMethod_cb _cb);
Desde su implementación en C++, las implementaciones del servidor deben mostrar Void()
, que es una función intercalada estática que muestra un objeto Return<void>
. Ejemplo de una implementación típica de un método de servidor con un parámetro de devolución de llamada:
Return<void> someMethod(someMethod_cb _cb) { // Do some processing, then call callback with return data hidl_vec<uint32_t> vec = ... _cb(vec); return Void(); };
Funciones sin valores devueltos
La firma de C++ de una función sin una sentencia generates
no tendrá un parámetro de devolución de llamada en la lista de parámetros. Su tipo de datos que se mostrará será Return<void>.
.
Funciones unidireccionales
Las funciones marcadas con la palabra clave oneway
son funciones asíncronas (los clientes no se bloquearán en su ejecución) y no tienen valores que se muestran. La firma de C++ de una función oneway
no tendrá un parámetro de devolución de llamada en la lista de parámetros, y su valor de retorno de C++ será Return<void>
.