Reputation: 71
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):
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.
Upvotes: 2
Views: 2064
Reputation: 4891
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
let someClassArg = UnsafeMutablePointer<OpaquePointer?>(objOpaquePointer)
Here someClassArg
is still a pointer to obj
that was passed in to mySwiftFunction()
, it's just cast to a different pointer type. However, C_exampleFunction()
needs a pointer to a pointer to obj
. Thus the code is most likely going to crash.
You can resolve this by replacing the problematic line with
let someClassArg = UnsafeMutablePointer<OpaquePointer?>.allocate(capacity: 1)
someClassArg.pointee = objOpaquePointer
There are other approaches, too. For example, you could pass objOpaquePointer
using inout
syntax; it would need to be a var
for that to work, though. You could also avoid using Unmanaged
like this:
let objUnsafeMutablePtr = UnsafeMutablePointer<AnyObject>.allocate(capacity: 1)
objUnsafeMutablePtr.pointee = obj
var objOpaquePtr : OpaquePointer! = OpaquePointer(objUnsafeMutablePtr)
C_exampleFunction(&objOpaquePtr)
(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 use Unmanaged
, you may want to use passRetained()
(and then takeRetainedValue()
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
Upvotes: 2