Dmitry Kandalov
01/10/2022, 6:52 PMCGDisplayMode
from macos CoreGraphics in Kotlin (1.6.10)? In particular, I can’t make the following code work:
fun main() {
val displayModes = CGDisplayCopyAllDisplayModes(1, null)!!.toNsArray()
val displayMode = displayModes.objectAtIndex(0)
println(displayMode) // prints <CGDisplayMode 0x600003648840> [{ BitsPerPixel = 32; ... }]
println(displayMode as? CGDisplayMode) // compilation error: java.lang.IllegalStateException: class CGDisplayMode... long stacktrace
println(displayMode as? CGDisplayModeRef) // prints null
println((displayMode as? NSObject)?.className) // prints __NSCFType
}
private fun CFArrayRef.toNsArray() = CFBridgingRelease(this) as NSArray
Sam
01/10/2022, 7:16 PMtoNSArray
function looks problematic. Does it work if you just cast the CFArrayRef to an NSArray without releasing it? You’ll have to release it at some point. It just looks like you’re casting a null to an NSArray. Maybe,
private fun CFArrayRef.toNSArray(): NSArrray {
val arr = this as NSArray
CFBridgingRelease(this)
return arr
}
It does feel like an awkward side affect to be releasing the reference in that function. You would get a crash if you called toNSArray twice on the same reference.Dmitry Kandalov
01/10/2022, 7:59 PMCGDisplayCopyAllDisplayModes(1, null) as NSArray
fails at runtime with kotlin.TypeCastException
.Dmitry Kandalov
01/10/2022, 8:00 PMfun main() {
val displayModes = CGDisplayCopyAllDisplayModes(1, null) as CFArrayRef
val displayMode = CFArrayGetValueAtIndex(displayModes, 0)!!
println(displayMode as? CGDisplayModeRef) // prints CPointer(raw=0x...)
println(CGDisplayModeGetWidth(displayMode as? CGDisplayModeRef)) // prints screen width
println(CGDisplayModeGetHeight(displayMode as? CGDisplayModeRef)) // prints screen height
}
But it’s not obvious to me how to convert it to NSArray (which as I understand should be convertable to List in Kotlin).Dmitry Kandalov
01/10/2022, 8:08 PMprivate fun CFArrayRef.toNsArray(): NSArray {
val result = this as NSArray // fails at runtime with kotlin.TypeCastException
CFBridgingRelease(this)
return result
}
I think overall it feels like the interop with macos API is a bit difficult and confusing.Sam
01/10/2022, 8:42 PMpointed
property, you should be able to get to the actual array.
public typealias CFArrayRef = kotlinx.cinterop.CPointer<cnames.structs.__CFArray>
Interacting with the lower level Core Foundation API is not fun in either Swift or Kotlin. It usually takes a while to work out the exact magic needed and unfortunately there are more people doing it in Swift than in Kotlin so it isn’t easy to google for.russhwolf
01/10/2022, 9:34 PMval arr = CFBridgingRelease(this) as NSArray
.russhwolf
01/10/2022, 9:34 PMthis
is the CFArrayRef
in Sam's functionrusshwolf
01/10/2022, 9:36 PMrusshwolf
01/10/2022, 9:36 PMrusshwolf
01/10/2022, 9:37 PMDmitry Kandalov
01/10/2022, 9:39 PMval arr = CFBridgingRelease(this) as NSArray
is different from
private fun CFArrayRef.toNsArray() = CFBridgingRelease(this) as NSArray
russhwolf
01/10/2022, 9:40 PMrusshwolf
01/10/2022, 9:40 PM