Как избежать ошибки «staticCFunction должна принимать несвязанный ...» в Kotlin Собственный, когда вызывается Kotlin функция обратного вызова из C? - PullRequest
0 голосов
/ 12 января 2020

Это общий вопрос о функциях обратного вызова, определенных в Kotlin Native, вызываемых C функциями.

Ради аргумента, допустим, я пытаюсь пройтись каталог в файловой системе рекурсивно, используя https://linux.die.net/man/3/nftw в Kotlin Native . (Я знаю, что есть другие способы сделать это, используя другие 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 ()", но как только лямбда-код содержит любое захваченное значение, я получаю следующую ошибку компилятора:

"kotlinx.cinterop.staticCFunction должна принять unbound, non-capturing function or lambda ".

Мой вопрос: есть ли рекомендуемый подход о том, как получить доступ к любому неглобальному состоянию из такого обратного вызова?

Я придумал неприятный обходной путь, используя глобальную переменную, так что это не то, что я ищу в первую очередь. Если есть общепринятое решение, использующее @ThreadLocal или что-то еще, пожалуйста, обсудите.

1 Ответ

3 голосов
/ 12 января 2020

Для собственных обратных вызовов в целом (не указывается c до nftw). Функция C должна принимать параметр void* userData и передавать его обратному вызову при вызове. Это позволяет передавать локальные данные в функцию обратного вызова вместо глобальных данных. Это имеет место даже в C / C ++.

Для этого конкретного случая (независимо от языка) на самом деле не существует способа сделать это без каких-либо глобальных данных (или JIT, но давайте не будем об этом думать). Таким образом, любой обходной путь должен быть мерзким.

Использование @ThreadLocal является «разумным мерзким» решением.

nftw - это просто не очень хорошо разработанный C интерфейс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...