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,469
  • 2
  • 21
  • 22
Ian Bytchek
  • 8,804
  • 6
  • 46
  • 72

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
  • 529,903
  • 94
  • 1,240
  • 1,382
  • 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