Estou trabalhando no agrupamento de uma API C ++ que fornece acesso a um armazenamento de dados (Hazelcast) em funções C, para que o armazenamento de dados também possa ser acessado a partir de código somente C.
A API Hazelcast C ++ para a estrutura de dados do Mapa é semelhante a esta:
auto map = hazelcastClient->client->getMap<int, string>(mapName);
map.put(key, value);
Utiliza tipos de modelo para key
e value
parâmetros. Como não existem modelos disponíveis em C, pensei em criar uma função de wrapper para cada especialização do getMap<T, U>
método. Ou seja, para cada tipo C. Embora eu saiba que existem signed
e unsigned
versões de tipos C, eu estou bem com a limitação do API para suportar apenas int
, double
, float
, char *
para o key
e value
.
Então, escrevi um pequeno script que gera automaticamente todas as combinações. As funções exportadas são assim:
int Hazelcast_Map_put_int_string(
Hazelcast_Client_t *hazelcastClient,
const char *mapName,
int key,
char *value,
char** errptr
);
int Hazelcast_Map_put_int_int(
Hazelcast_Client_t *hazelcastClient,
const char *mapName,
int key,
int value,
char** errptr
);
...
Gerando uma função para get
, set
, contains
com todas as combinações possíveis de key
e value
tipos aumenta a quantidade de código muito, e embora eu acho que gerar o código é uma boa idéia, ele adiciona complexidade adicional por ter que criar algum tipo de infra-estrutura de geração de código.
Outra idéia que posso imaginar é uma função genérica em C, assim:
int Hazelcast_Map_put(
Hazelcast_Client_t *hazelcastClient,
const char *mapName,
const void *key,
API_TYPE key_type,
const void *value,
API_TYPE value_type,
char** errptr
);
Que pode ser usado assim:
Hazelcast_Map_put(client, mapName, "key", API_TYPE_STR, "val", API_TYPE_STR, &err);
Isso torna um pouco mais fácil para o chamador, porque diminui o ônus de obter a especialização correta no meu código, mas perde a segurança do tipo e exige a conversão. Além disso, para passar um int, como void *
agora é o tipo de key
e value
, um elenco como (void *) (intptr_t) intVal
seria necessário no lado dos chamadores, o que novamente não é super agradável de ler e manter.
- Existe alguma terceira opção que não reconheça?
- Qual versão seria preferida pelos desenvolvedores C?
Estou mais inclinado a gerar automaticamente todas as combinações de tipos e criar uma função para cada uma, embora suponha que o arquivo de cabeçalho se torne bastante grande.
fonte
Respostas:
Gerar para todas as possibilidades não parecia ser uma solução muito boa para mim. A chave e os valores também podem ser objetos. Portanto, as possibilidades são infinitas :(
Você deu uma olhada na classe IMapImpl? Essa classe não usa tipos, mas os dados binários (que são fornecidos após a serialização). Portanto, outra solução seria escrever uma API que imitasse essa interface + fornecendo um utilitário de serialização que converta qualquer tipo especificado no binário necessário para essa interface.
Por exemplo
API:
Utilitário de serialização:
Pode ser necessário escrever essas funções auxiliares para tipos de objetos aos quais você gostaria de oferecer suporte. Esta pode ser uma interface viável. Há coisas a serem consideradas, como gerenciamento de memória.
A serialização é um assunto complexo, mas você certamente pode começar apoiando os tipos primitivos primeiro. Consulte http://docs.hazelcast.org/docs/3.6/manual/html-single/index.html#serialization e https://github.com/hazelcast/hazelcast/blob/master/hazelcast/src/main/java /com/hazelcast/internal/serialization/impl/ConstantSerializers.java para obter detalhes da serialização.
fonte