Funções

As funções em uma interface HIDL são mapeadas para métodos na declaração de classe C++ IFoo gerada automaticamente. O nome de cada função permanece o mesmo em C++; as seções a seguir descrevem como os argumentos e os valores de retorno do HIDL são traduzidos para C++.

Parâmetros de função

Os argumentos listados no arquivo .hal são mapeados para tipos de dados C++. Os argumentos que não são mapeados para um tipo primitivo do C++ são transmitidos por referência const.

Para cada função HIDL que tenha um valor de retorno (tenha uma instrução generates), a lista de parâmetros C++ para essa função tem um argumento adicional: uma função de callback chamada com os valores de retorno da função HIDL. Há uma exceção: se a cláusula generates contiver um único parâmetro que mapeia diretamente para uma primitiva C++, o callback será omitido. O callback é removido e o valor de retorno é retornado da função por uma instrução return normal.

Valores de retorno da função

As funções a seguir têm valores de retorno.

Erros de transporte e tipo de retorno

A instrução generates pode resultar em três tipos de assinaturas de função:

  • Para apenas um valor de retorno que é uma primitiva C++, o valor de retorno generates é retornado pelo valor da função em um objeto Return<T>.
  • Para casos mais complicados, os valores de retorno generates são retornados pelo parâmetro de callback fornecido com a chamada de função, e a função retorna Return<void>.
  • Quando nenhuma instrução generates existe, a função retorna Return<void>.

As chamadas RPC podem ocasionalmente encontrar erros de transporte, por exemplo, quando o servidor morre, quando os recursos de transporte são insuficientes para concluir a chamada ou quando os parâmetros transmitidos não permitem concluir a chamada (como a ausência de uma função de callback obrigatória). Os objetos Return armazenam indicações de erro de transporte e um valor T (exceto Return<void>).

Como as funções do lado do cliente e do servidor têm a mesma assinatura, a função do lado do servidor precisa retornar um tipo Return, mesmo que a implementação não sinalize erros de transporte. Os objetos Return<T> são construídos com Return(myTValue) (ou podem ser construídos implicitamente com mTValue, como em instruções return) e os objetos Return<void> são construídos com Void().

Os objetos Return<T> têm conversão implícita para e de seu valor T. É possível verificar se o objeto Return tem erros de transporte chamando o método isOk() dele. Essa verificação não é necessária. No entanto, se um erro ocorrer e não for verificado quando o objeto Return for destruído ou se uma conversão de valor T for tentada, o processo do cliente será encerrado e um erro será registrado. Se isOk() indicar um erro de transporte ou uma falha de chamada devido a um erro lógico no código do desenvolvedor (como transmitir nullptr como um callback síncrono), description() poderá ser chamado no objeto de retorno para retornar uma string adequada para registro. Nesses casos, não há como determinar quanto código pode ter sido executado no servidor como resultado da chamada com falha. O método isDeadObject() também é fornecido. Esse método indica que !isOk() ocorre porque o objeto remoto trava ou não existe mais. isDeadObject() sempre implica !isOk().

Retornar por valor

Se a instrução generates mapeia para uma única primitiva C++, nenhum parâmetro de callback estará na lista de parâmetros. Em vez disso, uma implementação fornece o valor de retorno T em um objeto Return<T>, que pode ser gerado implicitamente do tipo primitivo T. Por exemplo:

Return<uint32_t> someMethod() {
    uint32_t return_data = ...; // Compute return_data
    return return_data;
};

O método Return<*>::withDefault também é fornecido. Esse método fornece um valor nos casos em que o valor de retorno é !isOk(). Esse método também marca automaticamente o objeto de retorno como bom, para que o processo do cliente não seja encerrado.

Retornar usando o parâmetro de callback

Um callback pode transmitir o valor de retorno da função HIDL de volta ao autor da chamada. O protótipo do callback é um objeto std::function com parâmetros (extraídos da instrução generates) mapeados para tipos C++. O valor de retorno é nulo. O callback em si não retorna um valor.

O valor de retorno de uma função C++ com um parâmetro de callback tem o tipo Return<void>. A implementação do servidor é responsável apenas por fornecer o valor de retorno. Como os valores de retorno já foram transferidos usando o callback, o parâmetro de modelo T é void:

Return<void> someMethod(someMethod_cb _cb);

A partir da implementação em C++, as implementações do servidor precisam retornar Void(), que é uma função inline estática que retorna um objeto Return<void>. Exemplo de implementação de um método de servidor típico com um parâmetro de callback:

Return<void> someMethod(someMethod_cb _cb) {
    // Do some processing, then call callback with return data
    hidl_vec<uint32_t> vec = ...
    _cb(vec);
    return Void();
};

Funções sem valores de retorno

A assinatura C++ de uma função sem uma instrução generates não terá um parâmetro de callback na lista de parâmetros. O tipo de retorno será Return<void>..

Funções unidirecionais

As funções marcadas com a palavra-chave oneway são funções assíncronas (os clientes não são bloqueados na execução) e não têm valores de retorno. A assinatura C++ de uma função oneway não terá um parâmetro de callback na lista de parâmetros, e o valor de retorno do C++ será Return<void>.