当从 C 调用 Kotlin 回调函数时,如何避免 Kotlin Native 中的错误 "staticCFunction must take an unbound..."?

How to avoid the error "staticCFunction must take an unbound..." in Kotlin Native when a Kotlin callback function is called from C?

这是关于回调函数的一般性问题,在 Kotlin Native 中定义,由 C 函数调用。

为了论证,假设我正在尝试递归地遍历文件系统中的目录,使用 Kotlin Native 中的 https://linux.die.net/man/3/nftw。 (我知道还有其他方法可以做到这一点,使用其他C函数,但这不是本题的核心。)

nftw() 接受一个函数作为回调:

val directory = "//some/directory"
val callback = kotlinx.cinterop.staticCFunction {
            file: CPointer<ByteVar>?,
            stat: CPointer<stat>?,
            typeFlag: Int,
            b: CPointer<FTW>? ->

            val fileName = file?.toKString()
            println(fileName)
            val result = 0
            result
        }

val depth = 10
val flags = 0
platform.posix.nftw(directory, callback, depth, flags)

这适用于通过 "println()" 列出文件,但是只要 lambda 包含任何捕获的值,我就会收到以下编译器错误:

"kotlinx.cinterop.staticCFunction must take an unbound, non-capturing function or lambda".

我的问题是:是否有关于如何推荐的方法 从这样的回调中访问任何非全局状态?

我确实想出了一个使用全局变量的讨厌的解决方法,所以这不是我要找的主要内容。如果有普遍接受的使用@ThreadLocal 或其他方式的解决方案,请讨论。

一般用于本机回调(不特定于 nftw)。 C 函数应接受一个 void* userData 参数,并在调用时将其传递给回调。这允许您将本地数据而不是全局数据传递给回调。 即使在 C/C++.

中也是如此

对于这种特殊情况(无论使用何种语言),如果没有一些全局数据(或 JIT,但我们不要考虑它),实际上没有办法做到这一点。所以任何解决方法都必须是讨厌的。

使用 @ThreadLocal 是一个 "reasonable nasty" 解决方案。

nftw 不是一个设计良好的 C 接口。