Reputation: 45
I'm building a wrapper/interface for a C library with Swift 3. One of the functions that I need to call require a function pointer for callback as an argument.
In detail: after said function has successfully done the file operation it has to, it then calls the function the given argument pointer refers to - essentially letting me do other operations with said data
The function looks like this:
HSYNC MXDEF (Syncer)(DWORD h, DWORD t, QWORD p, SYNCPROC *proc, void *user);
The callback function type SYNCPROC
is defined as follows:
typedef void (CALLBACK SYNCPROC)(HSYNC h, DWORD c, DWORD d, void *user);
I have only been able to use the Syncer
function with setting the callback argument to nil so far.
I tried creating a function outside the Class as someone suggested:
func callbackCalled(handle: HSYNC, channel: DWORD, data: DWORD, user: UnsafeMutableRawPointer) -> Void {
print("callback called")
}
And I even tried this method within the Class:
var callbackTest : @convention(c) (_ handle: HSYNC, _ channel: DWORD, _ data: DWORD, _ user: UnsafeMutableRawPointer) -> Void = {
print("\($0) \($1) \($2) \($3)")
}
But however I tried / read upon this topic I always end up with this error message:
Cannot convert value of type 'Void' (aka '()') to expected argument type '(@convention(c) (HSYNC, DWORD, DWORD, UnsafeMutableRawPointer?) -> Void)!'
My question is: How am I supposed to satisfy the criteria regarding this type of a callback function?
I haven't been able to find any info regarding these types of callback functions, presumably due to my lack of knowledge and thorough understanding of the problem. Thank you in advance!
Upvotes: 3
Views: 3324
Reputation: 539715
Passing a global function as callback should work, but the last parameter
must be an optional UnsafeMutableRawPointer?
:
func callbackCalled(handle: HSYNC, channel: DWORD, data: DWORD, user: UnsafeMutableRawPointer?) -> Void {
print("callback called")
}
Syncer(h, c, d, callbackCalled, u)
Alternatively, pass a closure expression (and let compiler infer the types of the parameters):
Syncer(h, d, c, {
(handle, channel, data, user) in
// ...
}, u)
You can not pass an instance method as a callback, compare How to use instance method as callback for function which takes only func or literal closure.
If NULL
is not a valid value for the user parameter then you can
add
"Nullability annotations" to the C declaration, e.g.
typedef void (CALLBACK SYNCPROC)(HSYNC h, DWORD c, DWORD d, void * _Nonnull user);
and then it will be represented as a non-optional UnsafeMutableRawPointer
in Swift.
Upvotes: 4