Я работаю над упаковкой 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?
Я в основном склонен автоматически генерировать все комбинации типов и создавать функции для каждой, хотя заголовочный файл, я полагаю, станет довольно большим.
источник
Ответы:
Генерация для всех возможностей не выглядела как очень хорошее решение для меня. Ключ и значения также могут быть объектами. Следовательно, возможности безграничны :(
Вы смотрели на класс IMapImpl? Этот класс использует не типы, а двоичные данные (которые предоставляются после сериализации). Следовательно, другим решением было бы написание API, имитирующего этот интерфейс + предоставление утилиты сериализации, которая преобразует любой данный тип в двоичный файл, который необходим этому интерфейсу.
Например
API:
Утилита сериализации:
Возможно, вам придется написать эти вспомогательные функции для типов объектов, которые вы хотели бы поддерживать. Это может быть жизнеспособным интерфейсом. Есть вещи, которые следует учитывать, такие как управление памятью.
Сериализация - сложная тема, но вы можете начать с поддержки примитивных типов. См. Http://docs.hazelcast.org/docs/3.6/manual/html-single/index.html#serialization и https://github.com/hazelcast/hazelcast/blob/master/hazelcast/src/main/java. /com/hazelcast/internal/serialization/impl/ConstantSerializers.java для деталей сериализации.
источник