Я работаю над упаковкой API C ++, который предоставляет доступ к хранилищу данных (Hazelcast) в функции C, чтобы к хранилищу данных также можно было получить доступ из кода только на C.
API Hazelcast C ++ для структуры данных Map выглядит следующим образом:
auto map = hazelcastClient->client->getMap<int, string>(mapName);
map.put(key, value);
Он использует типы шаблонов для key
и value
параметров. Поскольку в C нет доступных шаблонов, я подумал о создании функции-оболочки для каждой специализации getMap<T, U>
метода. То есть для каждого типа C. Хотя я знаю , что есть signed
и unsigned
варианты типов C, я штраф с ограничением API для поддержки только int
, double
, float
, char *
для key
и value
.
Поэтому я написал небольшой скрипт, который автоматически генерирует все комбинации. Экспортируемые функции выглядят так:
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
);
...
Создание функции для get
, set
, contains
со всеми возможными комбинациями key
и value
типами увеличивает количество коды довольно много, и , хотя я думаю , что генерирование коды является хорошей идеей, это добавляет дополнительную сложность, имея для создания какого - то код , генерирующей инфраструктуры.
Другая идея, которую я могу представить, - это одна универсальная функция в C, например:
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
);
Который можно использовать так:
Hazelcast_Map_put(client, mapName, "key", API_TYPE_STR, "val", API_TYPE_STR, &err);
Это немного облегчает работу вызывающей стороны, поскольку переносит бремя получения правильной специализации на мой код, но снижает безопасность типов и требует приведения. Кроме того, для передачи типа int, как void *
это теперь является типом, key
и value
, (void *) (intptr_t) intVal
на стороне вызывающих будет необходим тип cast , что опять-таки не очень приятно читать и поддерживать.
- Есть ли третий вариант, который я не могу распознать?
- Какую версию предпочитают разработчики на C?
Я в основном склонен автоматически генерировать все комбинации типов и создавать функции для каждой, хотя заголовочный файл, я полагаю, станет довольно большим.