From <https://kotlinlang.org/docs/tutorials/native...
# kotlin-native
m
From https://kotlinlang.org/docs/tutorials/native/mapping-function-pointers-from-c.html: "We use the 
staticCFunction{..}
 helper function from Kotlin/Native to wrap a Kotlin lambda function into a C function pointer. It only allows having unbound and non-capturing lambda functions. For example, it is not able to use a local variable from the function. We may only use globally visible declarations." "globally visible declarations" -> how can access my global kotlin declarations inside the the lambda of
staticCFunction
, because I have tested some approaches and only could have access to functions that use kotlin global functions (like
println
), if I use some of my global scoped declarations my code fails on kotlin native call stack...
d
Does the C-api not offer some sort of
userPtr
?
👍 1
m
yes, I have a pointer and I am using it, but the pointer is for a Kotlin class that contains a
ConflatedBroadcastChannel
as a member, and every time I do:
Copy code
userPtr.asStableRef<MyKClass>().get().broadcaster.offer(Unit)
I have EXC_BAD_ACCESS in my Swift Code on iOS side...
I know that probably the C function is running in another thread and I am trying to calling something from my kotlin code... but I've tried to call the code using:
Copy code
dispatch_async(dispatch_get_main_queue()) {...}
and the problem still happens
d
In that case, you should use the pointer to make a wrapper function that can take a capturing lambda. (You can then capture the channel and other things)
m
I'm sorry, how can I "use the pointer to make a wrapper function"?
d
What is the signature of your function? (It would be easier to show you)
m
so, I have:
Copy code
class MyKClass {
    val broadcast = ConflatedBroadcastChannel<Unit>()

    val selfPtr: StableRef<MyKClass>
    
    init {
        selfPtr = StableRef.create(this)

        val callback: SomeCallbackClass = staticCFunction { value: SomeClassType, info: COpaquePointer? ->
            if (info == null) { return@staticCFunction }
            info.asStableRef<MyKClass>().get().broadcast.offer(Unit) // here causes EXC_BAD_ACCESS!
        }
        
        someNativeApi(selftPtr.asCPointer(), callback)
    }
}
that's my use case...
d
Copy code
class MyKClass {
    val broadcast = ConflatedBroadcastChannel<Unit>()
    
    init {
        someNativeApiWrapper() { value: SomeClassType ->
            broadcast.offer(Unit) // here causes EXC_BAD_ACCESS!
        }
    }
    
    fun someNativeApiWrapper(callback: (value: SomeClassType) -> Unit) {
        val callbackPtr = StableRef.create(callback)
        someNativeApi(callbackPtr.asCPointer(), staticCFunction { value: SomeClassType, info: COpaquePointer? ->
            if (info == null) { return@staticCFunction }
            val realCallbackPtr = info.asStableRef<(SomeClassType) -> Unit>().get()
            realCallbackPtr(value)
            // Might free StableRef here
        })
    }
}