Hello! Is there any way to make `staticCFunction` ...
# kotlin-native
z
Hello! Is there any way to make
staticCFunction
access non-global variables/functions? For example, in this function, I had to use
Mutex
, which is ugly and poorly readable 😢
Copy code
private val tempList = mutableListOf<String>()
private val mutex = Mutex()
suspend fun getWindowTexts(): List<String> {
    return mutex.withLock {
        EnumWindows(
            lpEnumFunc = staticCFunction { hWnd, lParam ->
                val text = memScoped {
                    val textVar = allocArray<UShortVar>(256)
                    GetWindowText!!(hWnd, textVar, 256)
                    textVar.toKString()
                }
                tempList.add(text)
                1
            }, 0L
        )
        val list = tempList.toList()
        tempList.clear()
        list
    }
}
e
no, because plain C function pointers are not closures
👌🏻 1
t
You can use StableRef to pass a Kotlin object (like
this
). Pass it to
lParam
parameter and you can access it from the callback. Make sure to dispose the StableRef when no longer needed, but not any earlier.
I think this will work (untested)
Copy code
val list = mutableListOf<String>()
val stableRef = StableRef.create(list)
EnumWindows(
    lpEnumFunc = staticCFunction { hWnd, pParam ->
        val stableRef2 =   pParam.toCPointer<CPointed>()!!.asStableRef<MutableList<String>>()
        val list2 = stableRef2.get()
        // TODO use list2
        1
    },
    lParam = stableRef.asCPointer().toLong()
)
stableRef.dispose()
// TODO use list
e
right, the callback's
lParam
can be anything you want, and a
StableRef
is a great way to get pointers to Kotlin objects across the C interface
it could even be a Kotlin lambda,
Copy code
val cb: (String) -> Boolean = { list.add(it) }
val stableRef = StableRef.create(cb)
EnumWindows(
    lpEnumFunc = staticCFunction { hWnd, param ->
        val cb: (String) -> Unit = pParam.toCPointer<CPointed>()!!.asStableRef()
        val text = memScoped { ... }
        if (cb(text)) 1 else 0.also { SetLastError(ERROR_something) }
    },
    lParam = stableRef.asCPointer().toLong(),
)