为#define指针地址创建绑定

时间:2019-07-03 00:30:18

标签: vala vapi

借助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类型。感谢您的帮助!

1 个答案:

答案 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对其进行了很好的总结。