There is a C struct:
struct SomeStruct;
And there is a C function which uses this struct as double pointer parameter:
C_exampleFunction(struct SomeStruct** someClass)
I would like to pass any Swift class or object to this function in order to use its functionality. However the C function on the Swift side only accepts UnsafeMutablePointer as argument:
mySwiftFunction(for obj: AnyObject) {
let objUnsafeMutableRawPointer = Unmanaged.passUnretained(obj).toOpaque()
let objOpaquePointer = OpaquePointer(objUnsafeMutableRawPointer)
let someClassArg = UnsafeMutablePointer<OpaquePointer?>(objOpaquePointer)
C_exampleFunction(someClassArg)
}
The code has always produce some memory error even if I deallocate the pointers. My main question is how can I add objects as UnsafeMutablePointer to a C function like this above?
I checked these sources (but no luck):
- https://tech.bakkenbaeck.com/post/swift-c-interop
- https://www.sitepoint.com/using-legacy-c-apis-swift/
- https://www.uraimo.com/2016/04/07/swift-and-c-everything-you-need-to-know/#pointers-conversion
- https://developer.apple.com/documentation/swift/unsafemutablepointer
- https://swift.org/migration-guide-swift3/se-0107-migrate.html
- How to use UnsafeMutablePointer<OpaquePointer> in Swift? -https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/using_imported_c_functions_in_swift
Error what I get is:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x6ba571ac0)
Thank you for your answers, feedbacks and especially your time in advance.
I think one can do relatively little with a Swift object passed to a C function via an incomplete type pointer, but if you need to do that, you are on a right track.
One problem I see with the code in your question is the line
Here
someClassArg
is still a pointer toobj
that was passed in tomySwiftFunction()
, it's just cast to a different pointer type. However,C_exampleFunction()
needs a pointer to a pointer toobj
. Thus the code is most likely going to crash.You can resolve this by replacing the problematic line with
There are other approaches, too. For example, you could pass
objOpaquePointer
usinginout
syntax; it would need to be avar
for that to work, though. You could also avoid usingUnmanaged
like this:(here we pass the opaque pointer as
inout
).Regardless of which approach is taken, one should be very careful about the lifetime of
obj
. For example, if you useUnmanaged
, you may want to usepassRetained()
(and thentakeRetainedValue()
when retrieving the object), but that depends on your use case.Here is another helpful resource about manual memory management:
https://developer.apple.com/documentation/swift/swift_standard_library/manual_memory_management