Funciones

Las funciones en una interfaz HIDL se asignan a métodos en la declaración de clase IFoo C++ generada automáticamente. El nombre de cada función sigue siendo el mismo en C++; Las siguientes secciones describen cómo los argumentos HIDL y los valores de retorno se traducen a C++.

Parámetros de función

Los argumentos enumerados en el archivo .hal se asignan a tipos de datos de C++. Los argumentos que no se asignan a un tipo primitivo de C++ se pasan mediante referencia constante.

Para cada función HIDL que tiene un valor de retorno (tiene una declaración generates ), la lista de parámetros de C++ para esa función tiene un argumento adicional: una función de devolución de llamada que se llama con los valores de retorno de la función HIDL. Hay una excepción : si la cláusula generates contiene un único parámetro que se asigna directamente a una primitiva de C++, se utiliza la elisión de devolución de llamada (la devolución de llamada se elimina y el valor de retorno se devuelve desde la función a través de una declaración return normal).

Valores de retorno de la función

Las siguientes funciones tienen valores de retorno.

Errores de transporte y tipo de devolución.

La declaración generates puede dar como resultado tres tipos de firmas de función:

  • Para un solo valor de retorno que sea una primitiva de C++, el valor de retorno generates se devuelve por valor de la función en un objeto Return<T> .
  • Para casos más complicados, los valores de retorno generates se devuelven a través del parámetro de devolución de llamada proporcionado con la llamada de función y la función devuelve Return<void> .
  • Para cuando no existe una declaración generates , la función devuelve Return<void> .

Las llamadas RPC ocasionalmente pueden encontrar errores de transporte, por ejemplo, cuando el servidor muere, cuando los recursos de transporte son insuficientes para completar la llamada o cuando los parámetros pasados ​​no permiten completar la llamada (como la falta de una función de devolución de llamada requerida). Los objetos Return almacenan indicaciones de error de transporte, así como un valor T (excepto Return<void> ).

Como las funciones del lado del cliente y del lado del servidor tienen la misma firma, la función del lado del servidor debe devolver 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 implícitamente a partir de mTValue , como en las declaraciones return ) y los objetos Return<void> se construyen con Void() .

Los objetos Return<T> tienen conversión implícita hacia y desde su valor T Se puede comprobar si hay errores de transporte en el objeto Return llamando a su método isOk() . Esta verificación no es obligatoria; sin embargo, si se produce un error y no se verifica en el momento en que se destruye el objeto Return , o se intenta una conversión del valor T , el proceso del cliente se cerrará y se registrará un error. Si isOk() indica un error de transporte o una falla de llamada debido a un error lógico en el código del desarrollador (como pasar nullptr como una devolución de llamada sincrónica), entonces se puede llamar a description() en el objeto Return para devolver una cadena adecuada para el registro. En tales 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() .

Retorno por valor

Si la declaración generates se asigna a una única primitiva de C++, no hay ningún parámetro de devolución de llamada en la lista de parámetros. En cambio, una implementación proporciona el valor de retorno T en un objeto Return<T> , que puede generarse implícitamente 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 de retorno es !isOk() . Este método también marca automáticamente el objeto devuelto como correcto para que el proceso del cliente no finalice.

Devolver usando el parámetro de devolución de llamada

Una devolución de llamada puede devolver el valor de retorno de la función HIDL a la persona que llama. El prototipo de la devolución de llamada es un objeto std::function con parámetros (tomado de la declaración generates ) asignados a tipos de C++. Su valor de retorno es nulo: la devolución de llamada en sí no devuelve ningún valor.

El valor de retorno de una función C++ con un parámetro de devolución de llamada tiene el tipo Return<void> . La implementación del servidor es responsable únicamente de proporcionar el valor de retorno. Como los valores de retorno ya se transfieren mediante la devolución de llamada, el parámetro de la plantilla T es void :

Return<void> someMethod(someMethod_cb _cb);

Desde su implementación de C++, las implementaciones del servidor deberían devolver Void() , que es una función estática en línea que devuelve un objeto Return<void> . Ejemplo de 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 de retorno

La firma C++ de una función sin una declaración generates no tendrá un parámetro de devolución de llamada en la lista de parámetros. Su tipo de devolución será Return<void>.

Funciones unidireccionales

Las funciones marcadas con la palabra clave oneway son funciones asincrónicas (los clientes no bloquearán su ejecución) y no tienen valores de retorno. La firma 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> .