Khanh Nguyen
Khanh Nguyen

Reputation: 11134

Convert UnsafeMutableRawPointer to UnsafeMutablePointer<T> in swift 3

I have this code

let grayData = UnsafeMutablePointer<UInt8>(other: malloc(width * height * sizeof(UInt8)))

Which doesn't compile in Swift 3. How do I fix this?

Upvotes: 12

Views: 12783

Answers (5)

Elye
Elye

Reputation: 60081

I believe in Swift 5, we can do so using (assuming T is UInt8)

let unsafeMutablePointer
    = unsafeMutableRawPointer.bindMemory(to: UInt8.self, capacity: capacity)

Upvotes: 1

anorskdev
anorskdev

Reputation: 1925

Thanks to Khanh Nguyen for answer above. If one needs to use calloc(), look at:

let imageData =  calloc(width * height, MemoryLayout<UInt32>.size).assumingMemoryBound(to: UInt32.self)

What I was finding is that I needed to actually use "calloc" in a graphics application to get a bitmap. What I saw is that if malloc or Swift's allocate(capacity:) were used, that the allocation had random garbage (as one might expect). If this was used as the starting point for getting a bitmap of an image, you would see the random garbage in the simulator if the image's background was clear. Real device apparently clears this when drawing the image, and simulator treats clear background as a no-op. Able to then make the following UIImage extension to get a bitmap (Swift 3.0):

extension UIImage {

    func unSafeBitmapData() -> UnsafeMutablePointer<UInt32>? {
        guard let cgImage = self.cgImage else { return nil }

        let width = Int(self.size.width)
        let height = Int(self.size.height)
        let bitsPerComponent = 8

        let bytesPerPixel = 4
        let bytesPerRow = width * bytesPerPixel
        let maxPix = width * height

        let imageData =  calloc(maxPix, MemoryLayout<UInt32>.size).assumingMemoryBound(to: UInt32.self)
        let colorSpace = CGColorSpaceCreateDeviceRGB()

        var bitmapInfo: UInt32 = CGBitmapInfo.byteOrder32Big.rawValue
        bitmapInfo |= CGImageAlphaInfo.premultipliedLast.rawValue & CGBitmapInfo.alphaInfoMask.rawValue
        guard let imageContext = CGContext(data: imageData, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo) else { return nil }
        imageContext.draw(cgImage, in: CGRect(origin: CGPoint.zero, size: self.size))

        return imageData
    }

}

Upvotes: 1

Kaz Yoshikawa
Kaz Yoshikawa

Reputation: 1637

I ran into a similar problem, but nothing to do with malloc. If your code needs to deal with C libraries with Swift 3, you have to deal with void * which is equivalent to UnsafeMutableRawPointer in Swift 3. Your code needs to treat it as a certain structure. But somehow, swift 3 compiler is being hard on me for casting. I spent some time to figured it out, and I like to share my code how to do that.

Here is the code to demonstrate casting UnsafeMutableRawPointer to UnsafeMutablePointer<T>, modify its pointee, and make sure the original Context is updated.

struct Context {
    var city = "Tokyo"
}

var context: Context = Context()
let rawPtr = UnsafeMutableRawPointer(&context)
let opaquePtr = OpaquePointer(rawPtr)
let contextPtr = UnsafeMutablePointer<Context>(opaquePtr)

context.city // "Tokyo"
contextPtr.pointee.city = "New York"
context.city // "New York"

Upvotes: 34

OOPer
OOPer

Reputation: 47876

In your case, you'd better use allocate(capacity:) method.

let grayData = UnsafeMutablePointer<UInt8>.allocate(capacity: width * height)

Upvotes: 11

Khanh Nguyen
Khanh Nguyen

Reputation: 11134

Found it

let grayData = malloc(width * height * MemoryLayout<UInt8>.size)!.assumingMemoryBound(to: UInt8.self)

Upvotes: 2

Related Questions