我想使用Vala破解现有的基于GLib的C项目。
基本上我正在做的是,在我的构建过程开始时,使用valac从我的.vala文件生成.c和.h文件,然后按照我任何.c或.h文件的方式编译生成的文件。
这可能不是最好的方式,但似乎在大多数情况下工作正常。
我的问题是我很难从Vala代码访问现有的C代码。是否有捷径可寻?
我已经尝试编写自己的.vapi文件(我对vala附带的工具没有任何好运),但我找不到任何关于如何编写这些文件的体面文档。
有没有?我是否需要其中一个文件来调用现有的C代码?
是的,要调用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,以便将所有内容链接在一起。
是的,要调用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,以便将所有内容链接在一起。
我对elmarco的答案唯一的补充是 extern
关键词。如果您正在尝试访问已在其中一个软件包或标准C / Posix库中使用的单个C函数,则可以通过这种方式轻松访问它。
对于用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中一样。
这个主题还有很多,但这应该给你一个概述。
从c访问您的vala代码可能更容易。所有你需要做的就是编译成C.