0

我正在尝试使用 czmq 为 zeromq 构建 Swift 绑定。

我在 xcode 中配置了一个桥接头,它似乎明白这一点,但我仍然收到此错误:

/Users/jjl/code/swiftzmq/src/zsock.swift:47:37: error: use of undeclared type 'zsock_t'
typealias zsock_ptr = UnsafePointer<zsock_t>

在 C 中使用它,如果我这样做(这是我的桥接头的确切内容),我将拥有这种类型:

#include <czmq.h>

我知道它被包含在内,因为它一直在抱怨其中一个头文件中的某些内容,直到我链接到正确的库路径。

我不知道从这里去哪里。您可以提供的任何帮助将不胜感激

我的项目在https://github.com/jjl/swiftzmq

4

1 回答 1

0

我弄清楚发生了什么事。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 类型。我们只是替换每一个出现的地方zsockszsockemacs 可以帮助解决这个问题):

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;
}

祝所有阅读快速包装图书馆的人好运!

于 2014-11-22T09:27:34.227 回答