5

I'm trying to convert this objc code to swift:

CGContextRef contextRef = CGBitmapContextCreate(NULL,
                                                proposedRect.size.width,
                                                proposedRect.size.height,
                                                CGImageGetBitsPerComponent(imageRef),
                                                0,
                                                colorSpaceRef,
                                                (CGBitmapInfo)kCGImageAlphaPremultipliedFirst);
NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithGraphicsPort:contextRef flipped:NO];

So far I ended up with this:

var bitmapContext: CGContext = CGBitmapContextCreate(data, UInt(proposedRect.width), UInt(proposedRect.height), CGImageGetBitsPerComponent(image), 0, colorSpace, CGBitmapInfo(CGImageAlphaInfo.PremultipliedFirst.toRaw()))
let context = NSGraphicsContext(graphicsPort: bitmapContext, flipped: false)

The problem is that CGBitmapContextCreate returns CGContext type and NSGraphicsContext initializer accepts graphicsPort as CMutableVoidPointer type. So how can I convert CGContext to CMutableVoidPointer?

related reverse type casting found here, but it didn't provide much help to me How to convert COpaquePointer in swift to some type (CGContext? in particular)

Community
  • 1
  • 1
chebur
  • 614
  • 8
  • 16

2 Answers2

2

I ended up with the reinterpretCast function returning intermediate Int variable for the bitmapContext address.

var bitmapContext: CGContext = CGBitmapContextCreate(...)

let bitmapContextAddress: Int = reinterpretCast(bitmapContext)
let bitmapContextPointer: CMutableVoidPointer = COpaquePointer(UnsafePointer<CGContext>(bitmapContextAddress))
let context = NSGraphicsContext(graphicsPort: bitmapContextPointer, flipped: false)
chebur
  • 614
  • 8
  • 16
  • 2
    Thanks for the answer! I think `reinterpretCast` is gone from the language, though; you need to use `unsafeBitCast` instead. – Sergey Kalinichenko Apr 11 '15 at 15:48
  • sure, you are right, but the NSGraphicsContext's object initializer had changed it's signature, so the bit casting is no longer required – chebur Apr 13 '15 at 07:58
0

The documentation here:https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/buildingcocoaapps/InteractingWithCAPIs.html

states the following:

When a function is declared as taking a CMutableVoidPointer argument, it can accept the same operands as CMutablePointer for any type Type.

From that, it should work like this:

var p: CMutablePointer<CGContext> = &bitmapContext
NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithGraphicsPort:p flipped:NO];

Extended practically, you should be able to pass in &bitmapContext directly to a CMutableVoidPointer argument.

Swift doesn't have "pointers" in the C sense.

Jack
  • 16,677
  • 8
  • 47
  • 51
  • Original type `CGContextRef` is already a pointer. So in objc I am able to make simple cast `void *pointer = CGBitmapContextCreate(...)` and get what I need. And in swift `&bitmapContext` is pointer to pointer `void **` and it is not exactly what the `NSGraphicsContext` accepts for `graphicsPort` argument – chebur Jun 19 '14 at 07:55
  • @chebur This is Swift, not C, not C++, not ObjC. There is no notion of pointers in Swift. If you do not accept or understand that, you will simply not get Swift. – Jack Jun 19 '14 at 11:34
  • What you trying to advice is to get pointer to `CGContextRef` by doing `&bitmapContext`. But [Typically graphicsPort is a CGContextRef (opaque type) object](https://developer.apple.com/library/mac/documentation/cocoa/reference/applicationkit/classes/NSGraphicsContext_Class/Reference/Reference.html#//apple_ref/occ/clm/NSGraphicsContext/graphicsContextWithGraphicsPort:flipped:). It means that the function expects exactly the `CGContextRef` value simply downcasted to `CMutableVoidPointer` (`void *` in terms of C), not pointer to `CGContextRef` as you adviced earlier. – chebur Jun 19 '14 at 12:37
  • Again, you are thinking in C terms. In Swift, `&` is not a reference operator and the bridging from ObjC to Swift handles passing the opaque type inside. i.e. `&bitmapContext` does **not** create a pointer to `CGContextRef`. There is no such thing as pointers in Swift. – Jack Jun 19 '14 at 12:44
  • Swift provides [various types for pointers to enable direct memory access](https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/buildingcocoaapps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-XID_16). There're examples inside to show proper usage of `&`. And so far `&` meaning is to _get a reference to a value_ – chebur Jun 19 '14 at 13:11
  • Btw, passing `&bitmapContext` leads to crash at runtime, and `reinterpretCast` works fine – chebur Jun 19 '14 at 13:22