Je travaille sur l'encapsulation d'une API C ++ qui donne accès à un magasin de données (Hazelcast) dans les fonctions C, afin que le magasin de données soit également accessible à partir de code C uniquement.
L'API Hazelcast C ++ pour la structure de données de la carte ressemble à ceci:
auto map = hazelcastClient->client->getMap<int, string>(mapName);
map.put(key, value);
Il utilise des types de modèles key
et des value
paramètres. Comme il n'y a pas de modèles disponibles en C, j'ai pensé à créer une fonction wrapper pour chaque spécialisation de la getMap<T, U>
méthode. Autrement dit, pour chaque type C. Même si je suis conscient qu'il existe signed
et unsigned
versions de types C, je suis très bien avec la limitation de l'API pour soutenir que int
, double
, float
, char *
pour key
et value
.
J'ai donc écrit un petit script, qui génère automatiquement toutes les combinaisons. Les fonctions exportées ressemblent à ceci:
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
);
...
Génération d' une fonction pour get
, set
, contains
avec toutes les combinaisons possibles key
et value
types augmente la quantité de code tout à fait beaucoup, et même si je pense que la génération du code est une bonne idée, il ajoute une complexité supplémentaire d'avoir à créer une sorte d'infrastructures génératrices de code.
Une autre idée que je peux imaginer est une fonction générique en C, comme ceci:
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
);
Qui peut être utilisé comme ceci:
Hazelcast_Map_put(client, mapName, "key", API_TYPE_STR, "val", API_TYPE_STR, &err);
Cela rend un peu plus facile pour l'appelant, car cela déplace la charge d'obtenir la spécialisation correcte sur mon code, mais il perd la sécurité du type et nécessite des transtypages. De plus, pour passer un int, comme void *
c'est maintenant le type de key
et value
, un cast comme (void *) (intptr_t) intVal
serait nécessaire du côté des appelants, ce qui n'est pas très agréable à lire et à maintenir.
- Y a-t-il une troisième option que je ne peux pas reconnaître?
- Quelle version serait préférée par les développeurs C?
Je suis surtout enclin à générer automatiquement toutes les combinaisons de types et à créer une fonction pour chacune, bien que le fichier d'en-tête devienne assez énorme, je suppose.