Работа с (U) Int в Kotlin Native C interop - PullRequest
0 голосов
/ 16 марта 2020

Я пытаюсь использовать библиотеку PiGPIO с Kotlin Native в качестве связанной библиотеки (без использования deamon). Поэтому я использую C взаимодействие с файлом .def, который ссылается на файл pigpio.h .

Это работает (мне удалось заставить мигать светодиод), но есть проблема с набором целых чисел. Хотя я не включил функцию экспериментальных целых чисел без знака, сгенерированные заглушки используют тип UInt.

Например, для параметров этой функции:

@kotlinx.cinterop.internal.CCall public external fun gpioSetMode(gpio: kotlin.UInt, mode: kotlin.UInt): kotlin.Int { /* compiled code */ }

Это нормально для меня поскольку они имеют тип unsigned в C, и я хочу, чтобы это было как можно более безопасным для типа:

int gpioSetMode(unsigned gpio, unsigned mode);

Теперь проблема в том, что значения, которые будут использоваться в качестве параметров для функций, определяется с помощью макроопределений в файле .h. Например, для параметра mode:

#define PI_INPUT  0
#define PI_OUTPUT 1

Сгенерированные Kotlin константы, соответствующие этим значениям, имеют тип Int:

public const val PI_INPUT: kotlin.Int /* compiled code */
public const val PI_OUTPUT: kotlin.Int /* compiled code */

Однако, несмотря на вызов функции с константой в качестве параметра возможно:

gpioSetMode(14, PI_OUTPUT) // compiles fine

Я не могу создать метод, который принимает режим в качестве параметра и использует его:

fun main() {
    setMode(PI_OUTPUT) // fails to compile (Type Mismatch)
}

fun setMode(mode : UInt) {
    gpioSetMode(14, mode)
}

Есть ли способ заставить все константы натуральных чисел иметь тип UInt?

1 Ответ

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

AFAIK, в инструменте cinterop такой опции нет.
На самом деле, можно сказать, что проблема возникает из-за заголовка библиотеки, не использующего литералы без знака в разделе «определение». Но это может быть опущено в C, так что этот заголовок в порядке. Этот инструмент немного тупее, поэтому он принимает все целочисленные литералы без дополнительного суффикса как набранный со знаком.
О том, как работает ваша сгенерированная функция. В Kotlin есть концепция умного приведения (см. здесь ), но здесь есть проблема. В этой части документации есть примечание о доступности смарт-кастинга только для проверок внутри модуля. В вашем случае gpioSetMode(gpio, mode) и PI_OUTPUT находятся в одном и том же модуле, а ваш setMode - в другом. Вот почему первый вызов компилируется, а второй нет.
Мне удалось обойти его в моем небольшом примере следующим образом: просто добавьте в свой код вот так, переопределив константу

import my.*
const val PI_OUTPUT = my.PI_OUTPUT

, где my - это пакет библиотеки, наиболее вероятно, pigpio для вы. После этого будут доступны умные преобразования для функций библиотеки и всех функций, которые вы объявите в этом модуле.

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