Создать привязку для адреса указателя #define - PullRequest
1 голос
/ 03 июля 2019

Создание некоторых пользовательских VAPI-определений с помощью превосходной записи из https://wiki.gnome.org/Projects/Vala/ManualBindings#Functions как мой гид. Но я не уверен, как переводить макросы типа «С», например:

// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |=  (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
#define GPIO_SET *(gpio+7)  // sets   bits which are 1 ignores bits which are 0#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
#define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH
#define GPIO_PULL *(gpio+37) // Pull up/pull down
#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock

.c код объявляет gpio как:

// I/O access
volatile unsigned *gpio;

В качестве определения .vapi я должен объявить INP_GPIO (g) как пустую функцию? то есть:

[CCode (cname = "INP_GPIO")]
public void inp_gpio(int val);

... или это делегат

public delegate void inp_gpio(int val);

Какие критерии мне следует использовать для определения типа вапи. Спасибо за вашу помощь!

1 Ответ

1 голос
/ 04 июля 2019

Хороший вопрос! Код выглядит так, как будто он напрямую обращается к адресу памяти GPIO и выглядит как Примеры кода RPIO GPIO - Прямой доступ к регистру . Препроцессор C заменяет INP_GPIO(g) на выражение, используя оператор &=. Выражение выполняет побитовую операцию над ячейкой памяти, рассчитанной слева от оператора.

Все, что нужно сделать Vala, это убедиться, что INP_GPIO(g) записано в файл C, а затем препроцессор C выполняет обмен. Таким образом, правильная привязка будет выглядеть примерно так:

[CCode (cname = "INP_GPIO")]
public void inp_gpio(int pin);

Делегат в Vala - это указатель на функцию в C, и код не будет вызывать адрес памяти, а записывает в него значение. Это не указатель на функцию в C, поэтому его не следует привязывать как делегат в Vala.

Использование GPIO - отличный пример использования Vala. Вы можете рассмотреть возможность использования API пространства пользователя ядра Linux. Это недавно изменилось в Linux 4.8 и отсутствует в Vala linux.vapi. Так что будет приветствоваться патч для использования linux / include / uapi / linux / gpio.h с Vala. По сути, это файловый интерфейс к /dev/gpiochipx с различными IOCTL для управления им. Для получения более подробной информации см. слайды . Если вы понимаете GMainContext и GSource, я думаю, что можно написать Vala GSource с g_source_add_unix_fd . Это вызвало бы событие в GMainContext при изменении в строке GPIO. Событие, являющееся просто другим именем для обратного вызова. Это было бы хорошим способом реализации кода приложения более высокого уровня в ответ на входные данные на линиях GPIO. GMainContext создается за кулисами при использовании GMainLoop или GApplication. Документация для Vala должна быть сделана все же.

Существует также libgpiod, который предоставляет библиотеку пользовательского пространства для взаимодействия с символьным интерфейсом устройства ядра. Для Vala это означало бы написание libgpiod.vapi для использования gpiod.h . В libgpiod также есть инструменты командной строки, и в этой статье приводится краткое изложение.

...