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 keye valueparâ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 signede unsignedversões de tipos C, eu estou bem com a limitação do API para suportar apenas int, double, float, char *para o keye 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, containscom todas as combinações possíveis de keye valuetipos 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 keye value, um elenco como (void *) (intptr_t) intValseria 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.