借助https://wiki.gnome.org/Projects/Vala/ManualBindings#Functions的出色写作,创建了一些自定义vapi def 作为我的指导。但是我不确定如何转换类似“ C”的函数宏:
// 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)声明为void函数吗?即:
[CCode (cname = "INP_GPIO")]
public void inp_gpio(int val);
...还是代表
public delegate void inp_gpio(int val);
我应该使用什么标准来识别vapi类型。感谢您的帮助!
答案 0 :(得分:1)
好问题!该代码看起来像是直接访问GPIO存储器地址,似乎来自RPi GPIO Code Samples - Direct register access。 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是一个很好的用例。您可能需要考虑使用Linux内核用户空间API。最近在Linux 4.8中进行了更改,并且不在Vala linux.vapi
中。因此,欢迎使用将linux/include/uapi/linux/gpio.h与Vala配合使用的补丁程序。实际上,它是/dev/gpiochipx
的文件接口,具有各种IOCTL来操纵它。有关更多详细信息,请参见这些slides。如果您了解GMainContext和GSource,我认为可以使用g_source_add_unix_fd编写Vala GSource。 GPIO线发生更改时,这将触发GMainContext中的事件。事件只是回调的另一个名称。这将是响应GPIO线上输入来实现更高级别应用程序代码的好方法。使用GMainLoop或GApplication时,会在后台创建GMainContext。不过Vala的文档需要完成。
还有libgpiod
提供了一个用户空间库来与内核字符设备接口进行接口。对于Vala而言,这意味着编写libgpiod.vapi以使用gpiod.h。 libgpiod还具有命令行工具,this article对其进行了很好的总结。