Quebra automática de idiomas da API do tipo de modelo C ++ em C

9

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.

Máx.
fonte
Muitos votos positivos, nenhuma opinião ainda. Eu acho que é um problema comum como embrulhar métodos digitados em modelo em C?
Max
Não tenho certeza se é comum. Votei porque achei o problema interessante.
MetaFight 9/16
Relacionado, embora não seja realmente tão útil aqui: stackoverflow.com/questions/1588788/…
Martin Ba

Respostas:

1

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:

struct Binary {
   byte *data;
   size_t length;
   int32_t dataType;
};
Binary *hazelcast_map_put(const Binary *key, const Binary *value);

Utilitário de serialização:

int hazelcast_binary_to_int(const Binary *data);

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.

ihsan demir
fonte
Eu acho que esse é o caminho a seguir no meu caso. Para pessoas fora do circuito, eu também fiz a mesma pergunta em um PR para o cliente hazelcast C ++ github.com/hazelcast/hazelcast-cpp-client/pull/127 e ihsan, o mantenedor desse cliente C ++, foi tão bom quanto para responder à minha pergunta aqui no SO também.
Max