Ich arbeite daran, eine C ++ - API zu verpacken, die den Zugriff auf einen Datenspeicher (Hazelcast) in C-Funktionen ermöglicht, damit auf den Datenspeicher auch über C-only-Code zugegriffen werden kann.
Die Hazelcast C ++ - API für die Map-Datenstruktur sieht folgendermaßen aus:
auto map = hazelcastClient->client->getMap<int, string>(mapName);
map.put(key, value);
Es werden Vorlagentypen key
und value
Parameter verwendet. Da in C keine Vorlagen verfügbar sind, habe ich mir überlegt, für jede Spezialisierung der getMap<T, U>
Methode eine Wrapper-Funktion zu erstellen . Das heißt, für jeden C-Typ. Obwohl ich bin mir bewusst , dass es signed
und unsigned
Versionen von C - Typen, ich bin gut mit der API - Begrenzung nur zu unterstützen int
, double
, float
, char *
für key
und value
.
Also habe ich ein kleines Skript geschrieben, das alle Kombinationen automatisch generiert. Die exportierten Funktionen sehen folgendermaßen aus:
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
);
...
Erzeugen eine Funktion für get
, set
, contains
mit allen möglichen Kombinationen von key
und value
Arten erhöht die Menge an Code ziemlich viel, und obwohl ich den Code denke Erzeugung eine gute Idee ist, fügt es zusätzliche Komplexität , indem er eine Art von Code-generierenden Infrastruktur zu schaffen.
Eine andere Idee, die ich mir vorstellen kann, ist eine generische Funktion in C wie diese:
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
);
Welches kann so verwendet werden:
Hazelcast_Map_put(client, mapName, "key", API_TYPE_STR, "val", API_TYPE_STR, &err);
Dies macht es für den Anrufer etwas einfacher, da es die Last der korrekten Spezialisierung auf meinen Code verlagert, aber die Typensicherheit verliert und Casts erfordert. Außerdem würde für die Übergabe eines Int, wie void *
es jetzt der Typ von key
und ist value
, eine Besetzung wie (void *) (intptr_t) intVal
auf der Anruferseite benötigt, was wiederum nicht besonders schön zu lesen und zu pflegen ist.
- Gibt es eine dritte Option, die ich nicht erkennen kann?
- Welche Version würden C-Entwickler bevorzugen?
Ich bin meistens geneigt, alle Typkombinationen automatisch zu generieren und für jede eine Funktion zu erstellen, obwohl die Header-Datei vermutlich ziemlich groß wird.
quelle
Antworten:
Das Generieren für alle Möglichkeiten schien mir keine sehr gute Lösung zu sein. Der Schlüssel und die Werte können auch Objekte sein. Daher sind die Möglichkeiten unendlich :(
Haben Sie sich die IMapImpl-Klasse angesehen? Diese Klasse verwendet keine Typen, sondern die Binärdaten (die nach der Serialisierung bereitgestellt werden). Daher würde eine andere Lösung darin bestehen, eine API zu schreiben, die diese Schnittstelle nachahmt und ein Serialisierungsdienstprogramm bereitstellt, das einen bestimmten Typ in die von dieser Schnittstelle benötigte Binärdatei konvertiert.
Z.B
API:
Dienstprogramm zur Serialisierung:
Möglicherweise müssen Sie diese Hilfsfunktionen für Objekttypen schreiben, die Sie unterstützen möchten. Dies kann eine brauchbare Schnittstelle sein. Es gibt Dinge zu beachten, wie z. B. Speicherverwaltung.
Serialisierung ist ein komplexes Thema, aber Sie können sicherlich zuerst mit der Unterstützung der primitiven Typen beginnen. Siehe http://docs.hazelcast.org/docs/3.6/manual/html-single/index.html#serialization und https://github.com/hazelcast/hazelcast/blob/master/hazelcast/src/main/java /com/hazelcast/internal/serialization/impl/ConstantSerializers.java für Details zur Serialisierung.
quelle