Making a copy of an UnsafePointer<UInt8>

My code gets some data from an OpenCV cv::Mat object, and passes it to some Swift code that takes it via an UnsafePointer<UInt8> parameter. This works fine until I want to make the call asynchronous (using a DispatchQueue), I think because the underlying cv::Mat gets deallocated by the caller before the async method completes.

So I want to make a copy of it to hold onto during the async operation. I tried this:

    let copy = UnsafeMutablePointer<UInt8>.allocate(capacity: inSourceBufferLength)
    copy.initialize(from: inSourceBuffer, count: inSourceBufferLength)
    
    self.queue.async
    {
       self.foo(data: copy, length: inSourceBufferLength)
    }

But that doesn't seem to be working. Is UnsafeMutablePointer<> not memory managed?

I'd also like to keep immutable semantics throughout, but I can forego that if it makes things really messy.

···

--
Rick Mann
rmann@latencyzero.com

It is not. Specifically, the code you posted creates a copy of the data and then never destroys it.

If I were in your shoes I’d construct a `Data` value from the unsafe pointer and then pass that around.

let source = Data(bytes: inSourceBuffer, count: inSourceBufferLength)
self.queue.async {
    let size = source.count
    source.withUnsafeBytes { (p: UnsafePointer<UInt8>) in
        self.foo(data: p, length: size)
    }
}

The main drawback to this is that you have to jump through the hoops to access the data unsafely. It might be easier to recast your consumer (the `foo(…)` method) in terms of `Data`. That’s what I generally do when I work with foreign APIs like this, that is, keep the data in ‘Swift space’ and only deal with foreign types at the boundaries.

Whether that makes sense here really depends on the specifics of your program. For example, if your program has lots of this boundary code, it might be nicer to just stick with the foreign type. Or build a specific wrapper that makes it easier to do this conversion.

Share and Enjoy

···

On 15 Nov 2017, at 04:16, Rick Mann via swift-users <swift-users@swift.org> wrote:

Is UnsafeMutablePointer<> not memory managed?

--
Quinn "The Eskimo!" <http://www.apple.com/developer/>
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

Is UnsafeMutablePointer<> not memory managed?

It is not. Specifically, the code you posted creates a copy of the data and then never destroys it.

Hmm. So it should leak, not crash. I wonder what I'm doing wrong.

If I were in your shoes I’d construct a `Data` value from the unsafe pointer and then pass that around.

let source = Data(bytes: inSourceBuffer, count: inSourceBufferLength)
self.queue.async {
   let size = source.count
   source.withUnsafeBytes { (p: UnsafePointer<UInt8>) in
       self.foo(data: p, length: size)
   }
}

The main drawback to this is that you have to jump through the hoops to access the data unsafely. It might be easier to recast your consumer (the `foo(…)` method) in terms of `Data`. That’s what I generally do when I work with foreign APIs like this, that is, keep the data in ‘Swift space’ and only deal with foreign types at the boundaries.

Whether that makes sense here really depends on the specifics of your program. For example, if your program has lots of this boundary code, it might be nicer to just stick with the foreign type. Or build a specific wrapper that makes it easier to do this conversion.

Thanks. I have to call this code from Objective-C, passing a pointer and length (which is how I get the raw data). I could create CGImages from that, and I might, since eventually the consumer will be implemented in Metal 2. But right now, I just have to get back to the raw data to do the processing, so it seemed like extra work to create a CGImage.

···

On Nov 15, 2017, at 00:48 , Quinn The Eskimo! via swift-users <swift-users@swift.org> wrote:
On 15 Nov 2017, at 04:16, Rick Mann via swift-users <swift-users@swift.org> wrote:

--
Rick Mann
rmann@latencyzero.com