开发者问题收集

在 Swift 3 中使用具有回调函数指针作为参数的 C API 函数

2016-10-30
3320

我正在用 Swift 3 为 C 库构建包装器/接口。我需要调用的函数之一需要一个函数指针作为回调参数。

详细说明:在所述函数成功完成其必须执行的文件操作后,它将调用给定参数指针指向的函数 - 本质上是让我对所述数据执行其他操作

该函数如下所示:

HSYNC MXDEF (Syncer)(DWORD h, DWORD t, QWORD p, SYNCPROC *proc, void *user);

回调函数类型 SYNCPROC 定义如下:

typedef void (CALLBACK SYNCPROC)(HSYNC h, DWORD c, DWORD d, void *user);

到目前为止,我只能将 Syncer 函数与将回调参数设置为 nil 一起使用。

我尝试按照某人的建议在类外创建一个函数:

func callbackCalled(handle: HSYNC, channel: DWORD, data: DWORD, user: UnsafeMutableRawPointer) -> Void { print("callback called")

我甚至在类中尝试了这种方法:

var callbackTest : @convention(c) (_ handle: HSYNC, _ channel: DWORD, _ data: DWORD, _ ... Void = { print("\($0) \($1) \($2) \($3)")

但是无论我如何尝试/阅读此主题,我总是得到此错误消息:

无法将类型“Void”(又名“()”)的值转换为预期参数类型“(@convention(c) (HSYNC, DWORD, DWORD, UnsafeMutableRawPointer?) -> Void)!”

我的问题是: 我应该如何满足有关此类回调函数的标准?

我无法找到有关这些类型的回调函数的任何信息,大概是因为我缺乏知识和对问题的透彻理解。提前谢谢您!

1个回答

将全局函数作为回调传递应该可行,但最后一个参数 必须是可选的 UnsafeMutableRawPointer? :

func callbackCalled(handle: HSYNC, channel: DWORD, data: DWORD, user: UnsafeMutableRawPointer?) -> Void {
    print("callback called")
}

Syncer(h, c, d, callbackCalled, u)

或者,传递闭包表达式(并让编译器推断参数的类型):

Syncer(h, d, c, {
    (handle, channel, data, user) in
    // ...
}, u)

不能 实例 方法作为回调传递,比较 如何使用实例方法作为仅采用 func 或文字闭包的函数的回调

如果 NULL 不是用户参数的有效值,那么您可以 添加 “可空性注解” 添加到 C 声明中,例如

typedef void (CALLBACK SYNCPROC)(HSYNC h, DWORD c, DWORD d, void * _Nonnull user);

然后它将在 Swift 中表示为非可选的 UnsafeMutableRawPointer

Martin R
2016-10-30