C++ 模板类型 API 的通用C语言包装方法

引自:C++ – Idiomatic wrapping of C++ template type API in C – iTecTec

注:google翻,待整理

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.

最近我正在包装一个 C++ API,它提供对 C 函数中数据存储 (Hazelcast) 的访问,以便也可以从纯 C 代码访问数据存储。

The Hazelcast C++ API for the Map datastructure looks like this:

Hazelcast C++ API 中的Map 数据结构的如下所示:

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 intdoublefloatchar * for key and value.

该程序使用模板类型作为键和值参数。 由于 C 中没有可用的模板,我考虑为 getMap<T, U> 方法的每个实例创建一个包装函数。 也就是说,对于每个 C 类型。 虽然我知道 C 类型有带符号和无符号版本,但我可以将 API 限制为仅支持键和值的 int、double、float、char *。

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 getsetcontains 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.

为 get、set、contains 和所有可能的键和值类型组合生成一个函数会大大增加代码量,虽然我认为生成代码是个好主意,但它增加了额外的复杂性,因为必须去另外编写生成器代码。

Another idea I can imagine is one generic function in C, like this:

另一个想法是 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
);

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.

这使调用者更容易一些,因为它转移了对我的代码进行正确专业化的负担,但它失去了类型安全性并且需要强制转换。 此外,为了传入一个 int,因为 void * 现在是键和值的类型,所以调用方需要像 (void *) (intptr_t) intVal 这样的强制转换,这又不是很好阅读和维护 .

  • Is there any third option, which I can't recognize?
  • Which version would be preferred by C developers?
  • 是否有第三种选择?
  • C 开发人员更喜欢哪个版本?

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. 

我主要倾向于自动生成所有类型组合并为每个组合创建一个函数,尽管我想头文件会变得非常大。

Best Answer

最佳答案

Generating for all possibilities did not look to be a very good solution to me. The key and values may be objects as well. Hence, the possibilities are infinite :(

为所有可能性生成对我来说并不是一个很好的解决方案。 键和值也可以是对象。 因此,可能性是无限的:(

Did you have a look at IMapImpl class? This class does not use types but the binary data (which is provided after serialization). Hence, another solution would be writing an API that mimics this interface + providing a Serialization utility which converts any given type to the binary that this interface needs.

你看过 IMapImpl 类吗? 此类不使用类型,而是使用二进制数据(在序列化后提供)。 因此,另一种解决方案是编写一个模仿此接口的 API + 提供一个序列化实用程序,该实用程序将任何给定类型转换为该接口所需的二进制数据。

例如API:

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

Serialization utility:

序列化函数为:

int hazelcast_binary_to_int(const Binary *data);

You may need to write these helper functions for object types that you would like to support. This may be a viable interface. There are things to be considered such as memory management.

可能需要为想要支持的对象类型编写这些辅助函数。 这也许是一个可行的接口方案。 但有些东西需要考虑,例如内存管理。

序列化是一个复杂的主题,可以首先支持原始类型。 请参阅以下文章了解序列化细节。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值