Search code examples
cswiftkotlinkotlin-multiplatformkotlin-native

CPointer in Kotlin-Multiplatform


I cannot find any samples on how to get CPointer in Kotlin Multiplatform, and the documentation that exists doesn't help much. In my iOS source set, I need to build the Kotlin equivalent of the following Swift code (only including relevant parts of the code):

  ...(hex: String) {

if hex.hasPrefix("#") {
    let start = hex.index(hex.startIndex, offsetBy: 1)
         let scanner = Scanner(string: hexColor)
         var hexNumber: UInt64 = 0



          if scanner.scanHexInt64(&hexNumber) {

            r = CGFloat((hexNumber & 0xff000000) >> 24) / 255
           ....

The specific part I am having problems with is

scanner.scanHexInt64(&hexNumber)

This is the Kotlin code and the question

//input to function - hex: String
    val scanner = NSScanner(hex)
    if (hex.startsWith("#")) {
        scanner.scanLocation = 1u
    }
    var hexNumber : UInt32 = 0u
    /*Type mismatch.
    Required:
    CPointer<UIntVar /* = UIntVarOf<UInt> */>?
    Found:
    UInt32 /* = UInt */
     */
    //HOW TO GET CPOINTER TO hexNumber?
    scanner.scanHexInt(hexNumber)

Per documentation: (link)

Pointers and arrays are mapped to CPointer<T>?.

But how?


Solution

  • Found an answer to my question. Have to use

    memScoped

    .

    memScoped {
            var pointed : UIntVar = alloc<UIntVar>()
            scanner.scanHexInt(pointed.ptr)
            val alpha: CGFloat = 1.0
            val pointedValue = pointed.value
            val r: CGFloat = (((pointedValue and 0xFF0000) shr 16)/255.0)
            ....
    }
    

    The only source on the internet on this (with regards to applying it to get the pointer) here - link

    memScoped

    inline fun <R> memScoped(block: MemScope.() -> R): R
    Runs given block providing allocation of memory which will be automatically disposed at the end of this scope
    

    Within it, use the extension function alloc() to obtain CVariable

    fun <reified T : CVariable> NativePlacement.alloc(): T
    

    Which then gives you access to the pointer via yet another extension function

    val <T : CPointed> T.ptr: CPointer<T>
    

    All very clear in retrospect, and clear that originally approached the problem in the wrong way, looking to get the pointer by something like CPointer<UInt> = ... Official documentation at https://kotlinlang.org/docs/reference/native/c_interop.html