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 key
e value
parametri. 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 signed
e unsigned
versioni di tipo C, sto bene con limitando l'API per supportare solo int
, double
, float
, char *
per key
e 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
, contains
con tutte le possibili combinazioni di key
e value
tipi 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 key
e value
, (void *) (intptr_t) intVal
sarebbe 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.