natario1
01/17/2024, 7:57 PMStableRef
and passing the long address around to be used later. In some edge cases, this can happen after the stable ref is disposed, but there’s no way to catch the exception!
• asStableRef
doesn’t throw
• StableRef.get
doesn’t throw
• dereferencing the result doesn’t throw in the Kotlin runtime, I get a segmentation fault
class Handle {
val ref = StableRef.create(this)
val address = ref.asCPointer().toLong()
fun doSomething() { ... }
fun dispose() { ref.dispose() }
companion object {
fun doSomething(address: Long) {
val handle = address.toCPointer<CPointed>()!!.asStableRef<Handle>().get()
handle.doSomething()
}
}
}
kevin.cianfarini
01/17/2024, 8:01 PMkevin.cianfarini
01/17/2024, 8:01 PMnatario1
01/17/2024, 8:42 PMHandle
, I’d rather have get()
throw? I don’t see any way to ensure unwrapping valid stable refs only, that wouldn’t have a big impact on performancekevin.cianfarini
01/17/2024, 8:44 PMnatario1
01/17/2024, 8:46 PMLandry Norris
01/17/2024, 9:18 PMnatario1
01/17/2024, 9:31 PMkevin.cianfarini
01/17/2024, 9:32 PMclass MyStableRef<T>(private val delegate: StableRef<T>) {
private var disposed: Boolean = false
fun dispose() {
check(!disposed)
delegate.dispose()
disposed = true
}
}
natario1
01/18/2024, 12:14 AMfun doSomething(address: Long)
. it is called by an external environment (JVM, through JNI) so I can’t pass KN objects, only the stable address - any wrapper would have to be stableref-ed itself.
But I think I just got some ideas that I can play with. It’s funny how simply describing a problem to someone else often brings new ideas for a solution.Landry Norris
01/18/2024, 1:17 AMdoSomething(address)
becomes handle.doSomething()
. Then the handle class checks for the ref to be non-null. This limits how much interaction there is between Kotlin and C, and provides nice boundaries to ensure memory safety.