A capo automatico dell'API tipo di modello C ++ in C


9

Sto lavorando al wrapping di un'API C ++ che fornisce l'accesso a un archivio dati (Hazelcast) nelle funzioni C, in modo che sia possibile accedere all'archivio dati anche dal codice C-only.

L'API Hazelcast C ++ per la struttura dati della mappa è simile alla seguente:

auto map = hazelcastClient->client->getMap<int, string>(mapName);
map.put(key, value);

Fa uso di tipi di template keye valueparametri. Poiché non ci sono modelli disponibili in C, ho pensato di creare una funzione wrapper per ogni specializzazione del getMap<T, U>metodo. Cioè, per ogni tipo C. Anche se sono consapevole che ci sono signede unsignedversioni di tipo C, sto bene con limitando l'API per supportare solo int, double, float, char *per keye value.

Così ho scritto una piccola sceneggiatura che genera automaticamente tutte le combinazioni. Le funzioni esportate si presentano così:

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
);

...

Generazione di una funzione per get, set, containscon tutte le possibili combinazioni di keye valuetipi aumenta la quantità di codice di un bel po ', e anche se credo che la generazione del codice è una buona idea, aggiunge ulteriore complessità di dover creare una sorta di infrastrutture di codice generatrice.

Un'altra idea che posso immaginare è una funzione generica in C, come questa:

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
);

Quale può essere usato in questo modo:

Hazelcast_Map_put(client, mapName, "key", API_TYPE_STR, "val", API_TYPE_STR, &err);

Questo rende un po 'più facile per il chiamante, perché sposta l'onere di ottenere la specializzazione corretta sul mio codice, ma perde la sicurezza del tipo e richiede cast. Inoltre, per passare a un int, come void *è ora il tipo di keye value, (void *) (intptr_t) intValsarebbe necessario un cast simile dal lato dei chiamanti, che di nuovo non è molto bello da leggere e mantenere.

  • Esiste una terza opzione che non riesco a riconoscere?
  • Quale versione sarebbe preferita dagli sviluppatori C?

Sono per lo più propenso a generare automaticamente tutte le combinazioni di tipi e creare una funzione per ciascuna, anche se suppongo che il file di intestazione diventerà piuttosto grande.


Molti voti, nessuna opinione ancora. Capisco che è un problema comune come avvolgere i metodi tipizzati modello in C?
Max

Non sono sicuro che sia comune. Ho votato perché trovo il problema interessante.
MetaFight

Correlato, anche se non molto utile qui: stackoverflow.com/questions/1588788/…
Martin Ba

Risposte:


1

Generare per tutte le possibilità non sembrava essere un'ottima soluzione per me. La chiave e i valori possono anche essere oggetti. Quindi, le possibilità sono infinite :(

Hai dato un'occhiata alla classe IMapImpl? Questa classe non utilizza tipi ma i dati binari (forniti dopo la serializzazione). Quindi, un'altra soluzione sarebbe scrivere un'API che imita questa interfaccia + fornendo un'utilità di serializzazione che converte qualsiasi dato tipo nel binario di cui questa interfaccia ha bisogno.

Per esempio

API:

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

Utilità di serializzazione:

int hazelcast_binary_to_int(const Binary *data);

Potrebbe essere necessario scrivere queste funzioni di supporto per i tipi di oggetti che si desidera supportare. Questa potrebbe essere un'interfaccia praticabile. Ci sono cose da considerare come la gestione della memoria.

La serializzazione è un argomento complesso, ma puoi sicuramente iniziare con il supporto prima dei tipi primitivi. Vedi 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 per i dettagli di serializzazione.


Penso che questa sia la strada da percorrere per il mio caso. Per le persone fuori dal giro, ho anche posto la stessa domanda in un PR al client C ++ hazelcast github.com/hazelcast/hazelcast-cpp-client/pull/127 e ihsan, il manutentore di quel client C ++, era così gentile per rispondere alla mia domanda anche qui su SO.
Max
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.