我正在包装一个C ++ API,该API提供对C函数中的数据存储(Hazelcast)的访问,以便也可以从仅C代码中访问数据存储。
用于Map数据结构的Hazelcast C ++ API如下所示:
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
和and 的类型value
一样(void *) (intptr_t) intVal
,在调用者那边需要强制转换,这同样也不是很容易阅读和维护。
- 还有我不认识的第三种选择吗?
- C开发人员将首选哪个版本?
尽管头文件会变得非常庞大,但我主要倾向于自动生成所有类型组合并为每个类型创建一个函数。