我弄清楚发生了什么事。swift interop 层不够聪明,无法理解 czmq 的作者以更好的代码为名在编译器工具链上玩的技巧,所以我们必须做一些 C 包装来隐藏它。
简单的位:
#include <czmq.h>
从桥接头中删除该行
- 添加一行导入您选择的另一个标题(我选择
szsocket.h
是因为它是 swift zsocket 包装器)
- 创建一个对应的 .c 文件和
#import <czmq.h>
较难的位:
您需要在标头中重新创建库使用的任何结构。在我的例子中,zsock_t
结构定义如下:
typedef struct zsock_t {
uint32_t tag; // Object tag for runtime detection
void *handle; // The libzmq socket handle
char *endpoint; // Last bound endpoint, if any
char *cache; // Holds last zsock_brecv strings
int type; // Socket type
size_t cache_size; // Current size of cache
} zsock_t;
我们像这样创建一个简单的包装器:
typedef struct szsock_t {
uint32_t tag; // Object tag for runtime detection
void *handle; // The libzmq socket handle
char *endpoint; // Last bound endpoint, if any
char *cache; // Holds last zsock_brecv strings
int type; // Socket type
size_t cache_size; // Current size of cache
} szsock_t;
您还需要重新创建这些结构中使用的任何 typedef。在这种情况下,轻而易举地没有其他人。这些都在新的头文件(.h)中
然后,您需要包装库中接受这些结构之一的每个函数。我们以zsock_new
函数为例。
首先,我们需要在标头中预先声明我们的版本以避免任何 zsock 类型。我们只是替换每一个出现的地方zsock
(szsock
emacs 可以帮助解决这个问题):
szsock_t *szsock_new (int type, const char *filename, size_t line_nbr);
接下来我们需要在 .c 文件中创建包装函数:
szsock_t *szsock_new (int type, const char *filename, size_t line_nbr) {
return (szsock_t *) zsock_new(type, filename, line_nbr);
}
注意我们如何在和使用内部 zsock 函数之间zsock_t
进行szsock_t
转换。这样做是安全的,因为 swift 编译器不会读取它,只会读取 c 编译器。
接下来,有一堆可变参数函数。这对我有用:
int szsock_bind (szsock_t *self, const char *format, ...) {
int ret;
va_list args;
va_start(args, format);
ret = zsock_bind( (zsock_t *) self, format, args);
va_end(args);
return ret;
}
祝所有阅读快速包装图书馆的人好运!