我正在尝试使用来自vala的c宏。在我看来,使用ccode指令应该可以做到这一点,但是我没有找到任何关于如何使用它的有意义的文档。
在"The Hacker's Guide to Vala"中有一个关于ccode参数的简短部分。
以及amailing list thread about calling a C macro from Vala with CCode。
但这两种资源都不能真正帮助我理解ccode的真正功能。它显然影响了vala生成c代码的方式,根据Hackers' Guide to Vala我可以推断,c code指令可能会直接影响遍历valas ast时ccode树的创建方式。
有谁能再解释一下ccode的功能吗?
最佳答案
不幸的是,没有太多关于ccode的文档是有意义的。您需要做的是将它与vala附带的vapi文件一起使用。最基本的是,您可能会使用如下宏:
[CCode(cname = "FOO", cheader_filename = "blah.h")]
public extern void foo();
在这里,我们设置
cname
(即,将被发送到c代码中的名称)和cheader_filename
(即,应该是#include
d的头文件)。大多数其他ccode属性控制数组的处理方式。array_length = false
表示数组的长度未知。这可以应用于参数或方法,表示它适用于返回类型。例如:[CCode(array_length = false)] public int[] x();
[CCode(array_null_terminated = true)] public FileStream[] y();
public int[] z();
在本例中,
x
将具有未知的数组长度,并且具有预期的c原型int *x(void)
,而y
假定具有以空结尾的数组,且预期的c原型FILE **y(void)
。最后,假设z
有一个数组长度输出参数(即int *z(int *length)
的原型,其中length
是指向存储返回数组长度的位置的指针。所有这些都可以应用于参数。如果有数组长度,但不是紧跟在数组后面的参数,则指定
array_length_pos
也很有用。如果参数是委托,target_pos
指定传递用户数据的位置(即,与函数指针一起传递的void*
)。还有多种ccode属性可用于委托、类和结构。
instance_pos
指定类/结构实例或委托用户数据的去向。所有位置参数都是用浮点数指定的。这允许对多个位置进行编码。例如,假设我们有一个C原型:void foo(void* userdata, int length, double *dbl_array, void(*handler)(double,void*));
然后我们可以写下:
[CCode(cname = "foo")]
public void foo([CCode(array_length_pos = 0.2)] double[] array, [CCode(target_pos = 0.1)] Handler func);
如果
Handler
被定义为其他地方的委托,则可以看到pos
值将参数放在参数0(即,开始)之后,然后按特定顺序放置。类和结构具有处理初始化、销毁和引用计数的函数,但这些函数相当简单。处理泛型也有点复杂。再说一遍,vapis是最好的洞察力来源。不过,这足以让你开始你的基本C函数和宏。