Идиоматическое обёртывание C ++ типа шаблона API в C

9

Я работаю над упаковкой 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?

Я в основном склонен автоматически генерировать все комбинации типов и создавать функции для каждой, хотя заголовочный файл, я полагаю, станет довольно большим.

Максимум
источник
Много голосов, пока нет мнения. Я понимаю, что это общая проблема, как обернуть шаблонные методы в C?
Макс
Я не уверен, что это распространено. Я проголосовал, потому что нахожу проблему интересной.
MetaFight
Связанные, хотя и не очень полезные, здесь: stackoverflow.com/questions/1588788/…
Мартин Ба

Ответы:

1

Генерация для всех возможностей не выглядела как очень хорошее решение для меня. Ключ и значения также могут быть объектами. Следовательно, возможности безграничны :(

Вы смотрели на класс IMapImpl? Этот класс использует не типы, а двоичные данные (которые предоставляются после сериализации). Следовательно, другим решением было бы написание API, имитирующего этот интерфейс + предоставление утилиты сериализации, которая преобразует любой данный тип в двоичный файл, который необходим этому интерфейсу.

Например

API:

struct Binary {
   byte *data;
   size_t length;
   int32_t dataType;
};
Binary *hazelcast_map_put(const Binary *key, const Binary *value);

Утилита сериализации:

int hazelcast_binary_to_int(const Binary *data);

Возможно, вам придется написать эти вспомогательные функции для типов объектов, которые вы хотели бы поддерживать. Это может быть жизнеспособным интерфейсом. Есть вещи, которые следует учитывать, такие как управление памятью.

Сериализация - сложная тема, но вы можете начать с поддержки примитивных типов. См. 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 для деталей сериализации.

Ихсан Демир
источник
Я думаю, что это путь для моего дела. Для тех, кто не в курсе, я также задал тот же вопрос в пиаре клиенту hazelcast на C ++ github.com/hazelcast/hazelcast-cpp-client/pull/127, и ihsan, сопровождающий этого клиента C ++, был так хорош, что чтобы ответить на мой вопрос здесь, на SO, тоже.
Макс