具有可变参数的Swift和C回调

时间:2015-05-20 17:45:54

标签: c swift variadic-functions

我试图在Swift中使用一个C API,它要求我使用可变参数将回调传递给函数,即:

extern GEOSContextHandle_t GEOS_DLL initGEOS_r(
                                    GEOSMessageHandler notice_function,
                                    GEOSMessageHandler error_function);

其中GEOSMessageHandler定义为:

typedef void (*GEOSMessageHandler)(const char *fmt, ...);

我应该如何处理?我尝试使用以下定义的两个类方法实现Objective-C类:

@interface HumboldtCallback : NSObject
+(void)noticeCallback:(const char *)args, ... NS_REQUIRES_NIL_TERMINATION;
+(void)errorCallback:(const char *)args, ... NS_REQUIRES_NIL_TERMINATION;
@end

但Swift不允许我访问它们。如果我将参数定义为void*,我可以从Swift访问它们:

var GEOS_HANDLE: COpaquePointer {
    let noticeCallbackPointer = HumboldtCallback.noticeCallback;
    let errorCallbackPointer = HumboldtCallback.errorCallback;
    return initGEOS_r(noticeCallbackPointer, errorCallbackPointer)
}

但是编译器仍然不满意:

Cannot invoke 'initGEOS_r' with an argument list of type '((UnsafeMutablePointer<Void>) -> Void, (UnsafeMutablePointer<Void>) -> Void)'

在将指针作为参数传递给init函数之前,我是否应该以某种方式将指针强制转换为回调函数?

1 个答案:

答案 0 :(得分:0)

您需要编写C函数而不是目标C方法。不幸的是,Swift会将这些转换成Swift Closure。但是,您可以在目标C中编写一个函数/方法来返回函数指针。这将阻止Swift将函数转换为闭包。即在你的objectiveC标题中:

void myCallback (const char *fmt, ...);
GEOSContextHandle_t getMyCallback ();

然后在类中实现getMyCallback,如下所示:

GEOSContextHandle_t getMyCallback () {
  return myCallback;
}

并实现您的回调函数。在Swift中你最终会得到:

initGEOS_r(getMyCallback(), ...)

我相信您可以使用普通的C头和.c文件而不是使用对象来执行此操作。