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.