Swift Unsafemutablepointer & Unsafemutablepointer<Unsafepointer<Sometype>>

Swift UnsafeMutablePointer & UnsafeMutablePointerUnsafePointerSomeType

I've managed to suss this out... I wasn't allocating the memory properly for rects and count

What I had was:

var rects: UnsafeMutablePointer<UnsafePointer<NSRect>> = nil
var count: UnsafeMutablePointer<Int> = nil

What ultimately fixed the issue was:

var rects: UnsafeMutablePointer<UnsafePointer<NSRect>> = UnsafeMutablePointer<UnsafePointer<NSRect>>.alloc(1)
var count: UnsafeMutablePointer<Int> = UnsafeMutablePointer<Int>.alloc(1)

Hope this helps someone else :)

edit If anyone is interested, here's what the swift code for the above turned out to be:

override func drawSelectionInRect(dirtyRect: NSRect) {
var primaryColor = NSColor.alternateSelectedControlColor().colorWithAlphaComponent(0.5)
var secondarySelectedControlColor = NSColor.secondarySelectedControlColor().colorWithAlphaComponent(0.5)

switch (self.selectionHighlightStyle){
case .Regular:
if (self.selected){
if self.emphasized{
primaryColor.set()
}else{
secondarySelectedControlColor.set()
}
let bounds = self.bounds

var rects: UnsafeMutablePointer<UnsafePointer<NSRect>> = UnsafeMutablePointer<UnsafePointer<NSRect>>.alloc(1)
var count: UnsafeMutablePointer<Int> = UnsafeMutablePointer<Int>.alloc(1)

self.getRectsBeingDrawn(rects, count: count)

let rectArrayPtr = UnsafeMutableBufferPointer(start: rects, count: count.memory)
var base = rectArrayPtr.baseAddress

for var i = 0; i < count.memory; i++ {
var currentRect = base.memory
let rect = NSIntersectionRect(bounds, currentRect.memory)
NSRectFillUsingOperation(rect, .CompositeSourceOver)
base.successor()
}

}
default:
super.drawSelectionInRect(dirtyRect)
}
}

edit

As per a further comment, the same has been achieved here with a less verbose approach (thanks to Paul Patterson below):

http://stackoverflow.com/questions/32536855/using-getrectsbeingdrawn-with-swift

Assigning UnsafeMutablePointer value to UnsafePointer without unsafeBitCast

You can create an UnsafePointer<T> from an UnsafeMutablePtr<T>
simply with

let ptr = UnsafePointer(mptr)

using the

/// Creates an immutable typed pointer referencing the same memory as the
/// given mutable pointer.
///
/// - Parameter other: The pointer to convert.
public init(_ other: UnsafeMutablePointer<Pointee>)

initializer of UnsafePointer. In your case that would for example be

p.left = UnsafePointer(leftVal)

Cast C struct double pointer to a Swift struct unsafe pointer

Let's think about that in terms of what's happening in C. When I do a cast of pointers in C, the data that represents the pointer type will now be treated as a pointer of a different type. The value of the pointer doesn't change, just how you treat it.

Swift doesn't like to do this kind of thing and doesn't encourage you to do it because while cheap, it's a fundamentally unsafe thing to do and can lead to corrupting data, jumping into space, bus errors, etc.

That doesn't mean that swift doesn't have the ability to do this. The link that you point to uses withUnsafePointerTo which tries to limit the scope of the use of the pointer. In your case, you probably want to look at unsafeBitCast (documentation here) which mimics the C pointer cast (it's not strictly the same as C casting in general, but for pointers it is).

let a:UnsafeMutablePointer<SomeType> = fetchASomeTypePointer()
let b = unsafeBitCast(a, to: UnsafeMutablePointer<SomeOtherType>.self)

This makes the data representing the pointer to SomeType now become a pointer to SomeOtherType.

Like I said before, this is a dangerous thing to do especially if you don't fully understand what you're doing.

Extension for Generic Type `UnsafeMutablePointerUInt8`

Swift 3.1 Update

As of Swift 3.1 (available with Xcode 8.3 beta), concrete same-type requirements are now supported. You can now just say:

extension UnsafeMutablePointer where Pointee == UInt8 {
func asArray(withLength length: Int) -> [Int] {
return UnsafeBufferPointer(start: self, count: length).map(Int.init)
}
}

Pre Swift 3.1

You can do this – although it's not particularly nice. You'll have to create a new protocol in order to 'tag' the UInt8 type, and then constrain your extension to that protocol. It also doesn't allow you to easily specify that the Int(...) initialiser can take a _UInt8Type input – you have to implement a hacky 'shadow' method to do that.

protocol _UInt8Type {
func _asInt() -> Int
}
extension UInt8 : _UInt8Type {
func _asInt() -> Int {
return Int(self)
}
}

// Change 'Pointee' to 'Memory' for Swift 2
extension UnsafeMutablePointer where Pointee : _UInt8Type {
func asArray(withLength length:Int) -> [Int] {
return UnsafeBufferPointer(start: self, count: length).map{$0._asInt()}
}
}

All in all I'd prefer to keep this fully generic and go with @AMomchilov's solution. I'm only really adding this for the sake of completion.

Although it's worth noting that having concrete same-type requirements for extensions (extension Type where Generic == SomeType) has been proposed as a part of the Swift Generics Manifesto – so hopefully this will be possible in a future version of Swift.

Using getRectsBeingDrawn: with Swift

This is what you want:

var rects = UnsafePointer<NSRect>()
var count = Int()
getRectsBeingDrawn(&rects, count: &count)

for i in 0 ..< count {

let rect = rects[i]

// do things with 'rect' here

}

You make two variables rects and count, and pass references to both of them, so they get filled with information.

After calling getRectsBeingDrawn, rects points to count rectangles, which you can access with a subscript, like an array.

Indirect initialization of memory via UnsafeMutablePointer types

You can achieve what you are looking for via withUnsafeMutablePointer(to:_:) like so:

let foo = Foo()

withUnsafeMutablePointer(to: &foo.person) { (ptr) -> Void in
initializeWithBob(ptr)
}

print(foo.person!.name) // outputs Bob

However, I wouldn't recommend this approach. IMHO it makes more sense to wrap the APIs you are working with in a C function that you can make 'nice' to call from Swift. The problem with your current approach is that this type of Swift is hard to read for Swift developers and also hard to read for Audio Toolbox developers.

How to represent Objc-C NSUInteger[] = {0,1,2} in Swift as UnsafeMutablePointerUInt?

You can simply pass a Swift [UInt] array as in-out argument with &, this passes the address of the array element storage to the (Objective-)C function:

var pageIndexes: [UInt] = [1, 2, 3]
ptp.printPDF(atPath: "path", pages: &pageIndexes, length: UInt(pageIndexes.count), copy: 1)

For more information, see

  • Using Imported C Functions in Swift,
  • Interacting with C Pointers.


Related Topics



Leave a reply



Submit