问题 Vala vapi文件文档


我想使用Vala破解现有的基于GLib的C项目。

基本上我正在做的是,在我的构建过程开始时,使用valac从我的.vala文件生成.c和.h文件,然后按照我任何.c或.h文件的方式编译生成的文件。

这可能不是最好的方式,但似乎在大多数情况下工作正常。

我的问题是我很难从Vala代码访问现有的C代码。是否有捷径可寻?

我已经尝试编写自己的.vapi文件(我对vala附带的工具没有任何好运),但我找不到任何关于如何编写这些文件的体面文档。

有没有?我是否需要其中一个文件来调用现有的C代码?


3393
2018-03-23 00:10


起源



答案:


是的,要调用C函数,您需要为它编写绑定。该过程描述于 http://live.gnome.org/Vala/Tutorial#Binding_Libraries_with_VAPI_Files但是,这并不直接适用于没有GObject编写的自定义函数或库。如果你有非GObject库的复杂绑定,你可能需要#vala IRC频道的帮助。

但是,大多数情况下,我们使用简单的vapi文件绑定一些autoconf定义或一些用简单C编写的函数,出于效率原因或破坏的vala,或其他任何原因。这是大多数人的做法:

myfunc.vapi

[CCode (cheader_filename = "myfunc.h")]
namespace MyFunc {
    [CCode (cname = "my_func_foo")]
    public string foo (int bar, Object? o = null);
}

myfunc.h(以及与项目链接的.c中的相应实现)

#include <glib-object.h>
char* my_func_foo(int bar, GObject* o)

example.vala可能是

using MyFunc;

void main() {
    baz = foo(42);
}

使用valac进行编译时,请使用 --vapidir= 给出myfunc.vapi的目录位置。根据您的构建系统,您可能需要将额外的参数传递给valac或gcc CFLAGS,以便将所有内容链接在一起。


15
2017-11-03 00:12



谢谢!我遇到的一个问题是,当我在myfunc.vapi中指定头文件时,valac的.c输出写入#include <myfunc.h>时,我真正想要的是#include“myfunc.h”。知道怎么解决这个问题吗?它可以解决吗? - Jordan
这应该不是什么大问题,只要文件没有安装在你的系统中,它就会在你的项目目录中打开,如果你提供带-I的路径(例如:-I $(topsrc_dir)) / libfoo的) - elmarco


答案:


是的,要调用C函数,您需要为它编写绑定。该过程描述于 http://live.gnome.org/Vala/Tutorial#Binding_Libraries_with_VAPI_Files但是,这并不直接适用于没有GObject编写的自定义函数或库。如果你有非GObject库的复杂绑定,你可能需要#vala IRC频道的帮助。

但是,大多数情况下,我们使用简单的vapi文件绑定一些autoconf定义或一些用简单C编写的函数,出于效率原因或破坏的vala,或其他任何原因。这是大多数人的做法:

myfunc.vapi

[CCode (cheader_filename = "myfunc.h")]
namespace MyFunc {
    [CCode (cname = "my_func_foo")]
    public string foo (int bar, Object? o = null);
}

myfunc.h(以及与项目链接的.c中的相应实现)

#include <glib-object.h>
char* my_func_foo(int bar, GObject* o)

example.vala可能是

using MyFunc;

void main() {
    baz = foo(42);
}

使用valac进行编译时,请使用 --vapidir= 给出myfunc.vapi的目录位置。根据您的构建系统,您可能需要将额外的参数传递给valac或gcc CFLAGS,以便将所有内容链接在一起。


15
2017-11-03 00:12



谢谢!我遇到的一个问题是,当我在myfunc.vapi中指定头文件时,valac的.c输出写入#include <myfunc.h>时,我真正想要的是#include“myfunc.h”。知道怎么解决这个问题吗?它可以解决吗? - Jordan
这应该不是什么大问题,只要文件没有安装在你的系统中,它就会在你的项目目录中打开,如果你提供带-I的路径(例如:-I $(topsrc_dir)) / libfoo的) - elmarco


我对elmarco的答案唯一的补充是 extern 关键词。如果您正在尝试访问已在其中一个软件包或标准C / Posix库中使用的单个C函数,则可以通过这种方式轻松访问它。


1
2018-04-13 09:09





对于用C编写的基于GLib的库,您可以尝试从C源生成gir文件: 瓦拉/绑定

手动完成也不是问题。假设您有一个库,它在C中定义SomelibClass1,并使用一个名为do_something的方法,该方法接受一个字符串。 头文件的名称是“somelib.h”。然后相应的vapi就像下面这样简单:

somelib.vapi:

[CCode (cheader_filename="somelib.h")]
namespace Somelib {
   public class Class1 {
      public void do_something (string str);
   }
}

可以在此处找到为非GLib库编写vapis的文档: 瓦拉/ LegacyBindings

这其实很简单。让我们从posix.vapi中摘录:

[Compact]
[CCode (cname = "FILE", free_function = "fclose", cheader_filename = "stdio.h")]
public class FILE {
    [CCode (cname = "fopen")]
    public static FILE? open (string path, string mode);

    [CCode (cname = "fgets", instance_pos = -1)]
    public unowned string? gets (char[] s);
}

这实现了以下C函数:

FILE *fopen (const char *path, const char *mode);
char *fgets (char *s, int size, FILE *stream);

丢弃instance_pos属性时,vala假定该对象是方法的第一个参数。这样就可以绑定大致面向对象的c构造。取消引用对象时,将调用compact-class的free_method。

方法,类,结构等的CCode(cname) - 属性必须是它的名称,就像它在C中一样。

这个主题还有很多,但这应该给你一个概述。


1
2017-12-24 09:18



虽然此链接可能会回答这个问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面发生更改,则仅链接答案可能会变为无效。 - mu 無
谢谢你的提示。我编辑了我的答案。 - Richard


从c访问您的vala代码可能更容易。所有你需要做的就是编译成C.


-1