Swift 和带有可变参数的 C 回调
Swift and C callbacks with variadic arguments
我正在尝试在 Swift 中使用 C API,它要求我使用可变参数将回调传递给函数,即:
extern GEOSContextHandle_t GEOS_DLL initGEOS_r(
GEOSMessageHandler notice_function,
GEOSMessageHandler error_function);
其中 GEOSMessageHandler 定义为:
typedef void (*GEOSMessageHandler)(const char *fmt, ...);
我该如何处理?我尝试使用定义如下的两个 class 方法来实现 Objective-C class:
@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 函数之前,我是否应该以某种方式将指针转换为回调函数?
您需要编写 C 函数而不是 objective C 方法。不幸的是 Swift 会将它们转换为 Swift 闭包。但是你可以在 objective C 中写一个 function/method 到 return 你的函数指针。这将阻止 Swift 将函数转换为闭包。即在你的 objectiveC header:
void myCallback (const char *fmt, ...);
GEOSContextHandle_t getMyCallback ();
然后在 class 中像这样实现 getMyCallback:
GEOSContextHandle_t getMyCallback () {
return myCallback;
}
并实现您的回调函数。在 Swift 你会得到:
initGEOS_r(getMyCallback(), ...)
我相信您可以使用纯 C header 和 .c 文件而不是使用 object.
我正在尝试在 Swift 中使用 C API,它要求我使用可变参数将回调传递给函数,即:
extern GEOSContextHandle_t GEOS_DLL initGEOS_r(
GEOSMessageHandler notice_function,
GEOSMessageHandler error_function);
其中 GEOSMessageHandler 定义为:
typedef void (*GEOSMessageHandler)(const char *fmt, ...);
我该如何处理?我尝试使用定义如下的两个 class 方法来实现 Objective-C class:
@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 函数之前,我是否应该以某种方式将指针转换为回调函数?
您需要编写 C 函数而不是 objective C 方法。不幸的是 Swift 会将它们转换为 Swift 闭包。但是你可以在 objective C 中写一个 function/method 到 return 你的函数指针。这将阻止 Swift 将函数转换为闭包。即在你的 objectiveC header:
void myCallback (const char *fmt, ...);
GEOSContextHandle_t getMyCallback ();
然后在 class 中像这样实现 getMyCallback:
GEOSContextHandle_t getMyCallback () {
return myCallback;
}
并实现您的回调函数。在 Swift 你会得到:
initGEOS_r(getMyCallback(), ...)
我相信您可以使用纯 C header 和 .c 文件而不是使用 object.