Kotlin Объект для CPointer - PullRequest
       39

Kotlin Объект для CPointer

0 голосов
/ 06 марта 2020

Я пытаюсь передать объект Kotlin в библиотеку C, которая передаст этот объект функции обратного вызова. Эта функция написана на Kotlin, поэтому я могу использовать этот объект и работать с ним. Однако я не смог найти способ конвертировать Kotlin Объект в CPointer. Единственное, что я нашел, это может быть то, что мне нужно, это fun createKotlinObjectHolder(any: Any?): NativePtr и fun <reified T : Any> unwrapKotlinObjectHolder(holder: Any?): T. Но даже если я использую только что созданный NativePtr, чтобы передать его функции развертки, произойдет сбой с сообщением об ошибке unrecognized selector sent to instance 0xXYZ. Что я делаю не так или не те функции, которые я должен использовать?

Пример кода с libcURL:

fun writeCallback(ptr: CPointer<ByteVar>, ignored: ULong, size: ULong, userData: COpaquePointer?): ULong {
    if (userData != null) {
        unwrapKotlinObjectHolder<StringBuilder>(userData.rawValue).append("Hello")
    }
    return size
}

fun main() {
    ...
    val curl = curl_easy_init()
    ...
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, staticCFunction(::writeCallback))

    val stringBuilder = StringBuilder()
    val nativePtr = createKotlinObjectHolder(stringBuilder)
    val cPtr = interpretCPointer<CPointed>(nativePtr)
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, cPtr)
    ...
}

Код скомпилирован в macOS.

1 Ответ

1 голос
/ 11 марта 2020

Существует класс StableRef, который следует использовать для переноса Kotlin экземпляров в таких случаях. Этот код должен работать правильно:

fun writeCallback(ptr: CPointer<ByteVar>, ignored: ULong, size: ULong, userData: COpaquePointer?): ULong {
    if (userData != null) {
        userData.asStableRef<StringBuilder>().get().append("Hello")
    }
    return size
}

fun main() {
    /* get a curl handle */
    val curl = curl_easy_init();
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, staticCFunction(::writeCallback))
    val stringBuilder = StringBuilder()
    val stableRef = StableRef.create(stringBuilder)
    val cPtr = stableRef.asCPointer()
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, cPtr)

    curl_easy_perform(curl)

    curl_easy_cleanup(curl)
    stableRef.dispose()
}

См. эту страницу документации для получения дополнительной информации.

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