I am trying to use a C library for a robotic project which should run on both macOS and Linux. I am trying to call a Swift callback function inside the C function passed as a parameter to the library call.
I tried the solutions proposed here and here, but they do not work.
As suggested in those answers, I pass in the userData
(or similar) object passed to the C function, an object which can call the Swift callback function.
But when I access the passed userData
object I get a Thread 2: EXC_BAD_ACCESS (code=1, address=0x20)
error on the second line of cHandler
function. And I am not able to figure out why.
Here the code:
public func subscribe(newMessageHandler: @escaping () -> Void) -> Result<Subscription> {
func cHandler(buffer: UnsafePointer<lcm_recv_buf_t>?, channel: UnsafePointer<Int8>?, userData: UnsafeMutableRawPointer?) {
guard let userData = userData else { return }
let subscribeUserData = Unmanaged<SubscribeUserData>.fromOpaque(userData).takeUnretainedValue()
subscribeUserData.handler()
}
let userData = SubscribeUserData(handler: newMessageHandler)
var userDataPointer = UnsafeRawPointer(Unmanaged.passUnretained(userData).toOpaque())
self.subscribeUserData = userData
self.subscribeUserDataPointer = userDataPointer
if let subscription = lcm_subscribe(context, "ExampleMessage", cHandler, &userDataPointer) {
return .success(subscription)
} else {
return .failure(nil)
}
}
Here is the definition of SubscribeUserData
, the object that I pass in the C function:
typealias NewMessageHandler = () -> Void
/// User data object passed in the subscribe C handler function. Needed to pass in a Swift handler function.
class SubscribeUserData {
let handler: NewMessageHandler
init(handler: @escaping NewMessageHandler) {
self.handler = handler
}
}