当从 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 接口。
这是关于回调函数的一般性问题,在 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 接口。