当从 C 调用 Kotlin 回调函数时,如何避免 Kotlin Native 中出现错误“staticCFunction Must take an unbound...”?

tre*_*ere 1 kotlin kotlin-native

这是一个关于回调函数的一般问题,在 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)
Run Code Online (Sandbox Code Playgroud)

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

“kotlinx.cinterop.staticCFunction 必须采用未绑定、非捕获函数或 lambda”。

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

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

Dom*_*her 5

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

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

使用@ThreadLocal是一个“合理的令人讨厌”的解决方案。

nftw只是设计不完善的 C 接口。