Ajuste idiomático de la plantilla tipo C ++ API en C

9

Estoy trabajando en envolver una API de C ++ que proporciona acceso a un almacén de datos (Hazelcast) en funciones C, para que también se pueda acceder al almacén de datos desde el código C-only.

La API de Hazelcast C ++ para la estructura de datos del mapa tiene este aspecto:

auto map = hazelcastClient->client->getMap<int, string>(mapName);
map.put(key, value);

Hace uso de tipos de plantillas keyy valueparámetros. Como no hay plantillas disponibles en C, pensé en crear una función de contenedor para cada especialización del getMap<T, U>método. Es decir, para cada tipo de C. Aunque soy consciente de que hay signedy unsignedlas versiones de los tipos C, estoy bien con la limitación de la API para soportar sólo int, double, float, char *para keyy value.

Entonces escribí un pequeño script, que genera automáticamente todas las combinaciones. Las funciones exportadas se ven así:

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
);

...

Generar una función de get, set, containscon todas las combinaciones posibles de keyy valuetipos aumenta la cantidad de código mucho, y aunque creo que la generación del código es una buena idea, que añade complejidad adicional al tener que crear algún tipo de infraestructura de generación de código.

Otra idea que puedo imaginar es una función genérica en C, como esta:

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
);

Que se puede usar así:

Hazelcast_Map_put(client, mapName, "key", API_TYPE_STR, "val", API_TYPE_STR, &err);

Esto lo hace un poco más fácil para la persona que llama, ya que cambia la carga de obtener la especialización correcta en mi código, pero pierde la seguridad de tipo y requiere moldes. Además, para pasar un int, como void *ahora es el tipo de keyy value, (void *) (intptr_t) intValse necesitaría un reparto como en el lado de las personas que llaman, lo que de nuevo no es súper agradable de leer y mantener.

  • ¿Hay alguna tercera opción que no pueda reconocer?
  • ¿Qué versión preferirían los desarrolladores de C?

Estoy más inclinado a generar automáticamente todas las combinaciones de tipos y crear una función para cada una, aunque supongo que el archivo de encabezado será bastante grande.

Max
fuente
Muchos votos a favor, todavía no hay opinión. Supongo que es un problema común cómo envolver los métodos escritos con plantilla en C?
Max
No estoy seguro de que sea común. He votado porque encuentro el problema interesante.
MetaFight
Relacionado, aunque no es realmente tan útil aquí: stackoverflow.com/questions/1588788/…
Martin Ba

Respuestas:

1

Generar para todas las posibilidades no parecía ser una muy buena solución para mí. La clave y los valores también pueden ser objetos. Por lo tanto, las posibilidades son infinitas :(

¿Has echado un vistazo a la clase IMapImpl? Esta clase no usa tipos sino los datos binarios (que se proporcionan después de la serialización). Por lo tanto, otra solución sería escribir una API que imite esta interfaz + que proporcione una utilidad de serialización que convierta cualquier tipo dado al binario que necesita esta interfaz.

P.ej

API:

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

Utilidad de serialización:

int hazelcast_binary_to_int(const Binary *data);

Es posible que deba escribir estas funciones auxiliares para los tipos de objetos que le gustaría admitir. Esta puede ser una interfaz viable. Hay cosas a tener en cuenta, como la gestión de la memoria.

La serialización es un tema complejo, pero seguramente puede comenzar apoyando primero los tipos primitivos. Ver http://docs.hazelcast.org/docs/3.6/manual/html-single/index.html#serialization y https://github.com/hazelcast/hazelcast/blob/master/hazelcast/src/main/java /com/hazelcast/internal/serialization/impl/ConstantSerializers.java para obtener detalles sobre la serialización.

ihsan demir
fuente
Creo que este es el camino a seguir para mi caso. Para las personas fuera del circuito, también hice la misma pregunta en un RP al cliente de Hazelcast C ++ github.com/hazelcast/hazelcast-cpp-client/pull/127 e ihsan, el encargado de mantener ese cliente de C ++, fue tan amable como para responder a mi pregunta aquí también sobre SO.
Max