I'm working on wrapping a C++ API which provides access to a data store (Hazelcast) in C functions, so that the data store can also be accessed from C-only code.
The Hazelcast C++ API for the Map datastructure looks like this:
auto map = hazelcastClient->client->getMap<int, string>(mapName);
map.put(key, value);
It makes use of template types for key
and value
parameters. As there are no templates available in C, i thought about creating a wrapper function for each specialization of the getMap<T, U>
method. That is, for each C type. Although I'm aware that there are signed
and unsigned
versions of C types, I'm fine with limiting the API to support only int
, double
, float
, char *
for key
and value
.
So I wrote a small script, that auto-generates all combinations. The exported functions look like this:
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
);
...
Generating a function for get
, set
, contains
with all possible combinations of key
and value
types increases the amount of code quite a lot, and although I think generating the code is a good idea, it adds additional complexity by having to create some kind of code-generating infrastructure.
Another idea I can imagine is one generic function in C, like this:
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
);
Which can be used like this:
Hazelcast_Map_put(client, mapName, "key", API_TYPE_STR, "val", API_TYPE_STR, &err);
This makes it a bit easier for the caller, because it shifts the burden of getting the correct specialization on my code, but it looses type safety and requires casts. Also, for passing in an int, as void *
is now the type of key
and value
, a cast like (void *) (intptr_t) intVal
would be needed on the callers side, which again isn't super nice to read and maintain.
- Is there any third option, which I can't recognize?
- Which version would be preferred by C developers?
I'm mostly inclined to auto-generate all type combinations and create a function for each, although the header file will become quite huge I suppose.