0

I have problem when try to call Swift instance method from c callback.

Error: "A C function pointer cannot be formed from a closure that captures context."

linphone_core_cbs_set_registration_state_changed(cbs) { (lc, cfg, state, message) in            
        switch state{ 
          case LinphoneRegistrationOk:
            print("LinphoneRegistrationOk")        
            self.call()        
        }

func call() {        
    let account = "test"
    let domain = "sip.linphone.org"
    let identity = "sip:" + account + "@" + domain
    linphone_core_invite(lc, identity)
}
kritikaTalwar
  • 1,730
  • 1
  • 17
  • 25
Stefan Simic
  • 183
  • 1
  • 6
  • Possible duplicate of [How to use instance method as callback for function which takes only func or literal closure](https://stackoverflow.com/questions/33260808/how-to-use-instance-method-as-callback-for-function-which-takes-only-func-or-lit) – Martin R Apr 16 '18 at 07:55

1 Answers1

1

If you have the ability to pass an arbitrary void* as a context then using Unmanaged<SelfType>.passUnretained(self).toOpaque() and converting it back with Unmanaged<SelfType>.fromOpaque(context).takeUnretainedValue() is the best solution.

But based on your small snippet of (lc, cfg, state, message) none of them seem like a context pointer. So getting self back is still possible but likely more complex. Because you will need to create a global/static piece of data that can be accessed from inside your closure in a safe manner. Some ideas of how you can do this are below:

1) You can do this with just a simple global/static if you know that is safe.

2) You can use thread local storage and store a pointer to self and cast it back and forth in the same way as if you had the void* argument and used Unmanaged. This one of course requires that your C callback be raised on the same thread where you store the value.

3) If you have access to a unique identifier that both Swift and C can access that will continue to be valid and accessible in your callback you can create a map of type [UniqueIdentifierAccessibleBySwiftAndC: TypeOfSelf] and use that to get self back.

bscothern
  • 1,894
  • 11
  • 15