Sto lavorando su una API C ++ che fornisce accesso a un archivio dati (Hazelcast) nelle funzioni C, in modo che l'archivio dati sia accessibile anche dal codice C-only.
L'API C ++ Hazelcast per la struttura dati della mappa ha il seguente aspetto:
auto map = hazelcastClient->client->getMap<int, string>(mapName);
map.put(key, value);
Utilizza i tipi di modello per i parametri key
e value
. Poiché non ci sono modelli disponibili in C, ho pensato di creare una funzione wrapper per ogni specializzazione del metodo getMap<T, U>
. Cioè, per ogni tipo di C. Sebbene io sappia che ci sono signed
e unsigned
versioni di tipi C, sto bene limitando l'API per supportare solo int
, double
, float
, char *
per key
e value
.
Quindi ho scritto un piccolo script, che genera automaticamente tutte le combinazioni. Le funzioni esportate hanno questo aspetto:
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
);
...
Generare una funzione per get
, set
, contains
con tutte le possibili combinazioni di key
e value
tipi aumenta la quantità di codice molto, e anche se penso che generare il codice sia una buona idea, aggiunge ulteriore complessità dovendo creare una sorta di infrastruttura di generazione del codice.
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
);
Che 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 un int, come void *
è ora il tipo di key
e value
, sarebbe necessario un cast come (void *) (intptr_t) intVal
sul lato chiamanti, che di nuovo non è super bello da leggere e mantenere .
- C'è qualche terza opzione, che non riesco a riconoscere?
- Quale versione sarebbe preferibile agli sviluppatori C?
Sono per lo più propenso a generare automaticamente tutte le combinazioni di tipi e creare una funzione per ciascuna, anche se il file di intestazione diventerà piuttosto enorme, suppongo.