2

I have a very simple function in C and its pointer gets passed into Swift.

void callback() {
    NSLog(@"such pointer…");
}

How can it be invoke in Swift using ONLY the pointer? This is NOT about simply invoking it – it works fine when invoked directly. Tried the following and different variations with signature casting, but it always crashes:

let pointer: UnsafePointer<@convention(c)() -> ()> = UnsafePointer(bitPattern: …)
let callback: @convention(c)() -> () = pointer.memory
Swift.print(callback) // (Function)
callback() // Handling crash with signal 11...

Tried defining Callback type with typedef void(*Callback)(); – same thing:

let pointer: UnsafePointer<Callback> = UnsafePointer(bitPattern: …)
let callback: Callback = pointer.memory
Swift.print(callback) // (Function)
callback() // Handling crash with signal 11...

To check that it actually works and points to the right address I have another Objective-C function, which works as expected when invoked from Swift with the callback pointer.

void invokeCallback(uintptr_t callback) {
    ((void (*)()) callback)(); // such pointer…
}
Avi
  • 7,298
  • 1
  • 19
  • 22
Ian Bytchek
  • 8,424
  • 5
  • 40
  • 71

1 Answers1

4

The same approach as in Swift: How to call a C function loaded from a dylib should work here.

Example for Swift 3 (assuming that funcPtr is a UnsafeRawPointer containing the function's address):

// Define function type:
typealias callbackFunc = @convention(c) () -> Void

// Convert pointer to function type:
let callback = unsafeBitCast(funcPtr, to: callbackFunc.self)

// Call function:
callback()

Of course the type alias must match the actual function signature, and the function needs to be a "pure" C function (not an Objective-C method).

Community
  • 1
  • 1
Martin R
  • 510,973
  • 84
  • 1,183
  • 1,314
  • 1
    Hah i was trying all kinds of random shit trying to figure this out. `@convention(c)` is the ticket – Alexander Nov 13 '16 at 07:46
  • Ha, I've seen a couple of your answers with `unsafeBitCast`, shame didn't try it first. This is a lifesaver. Thanks Martin! – Ian Bytchek Nov 13 '16 at 10:44