Convert UnsafeMutableRawPointer to UnsafeMutablePo

2020-07-06 07:18发布

问题:

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?

回答1:

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

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


回答2:

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"


回答3:

Found it

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


回答4:

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
    }

}