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 key
y value
pará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 signed
y unsigned
las versiones de los tipos C, estoy bien con la limitación de la API para soportar sólo int
, double
, float
, char *
para key
y 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
, contains
con todas las combinaciones posibles de key
y value
tipos 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 key
y value
, (void *) (intptr_t) intVal
se 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.
fuente
Respuestas:
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:
Utilidad de serialización:
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.
fuente