我想使用Vala破解现有的基于GLib的C项目。
基本上我正在做的是,在构建过程开始时,使用valac从我的.vala文件生成.c和.h文件,然后按照我任何方式编译生成的文件.c或。 h文件。
这可能不是最好的方式,但似乎在大多数情况下工作正常。
我的问题是我很难从Vala代码访问现有的C代码。是否有捷径可寻?
我已经尝试编写自己的.vapi文件(我对vala附带的工具没有任何好运),但我找不到任何关于如何编写这些文件的体面文档。
有没有?我是否需要其中一个文件来调用现有的C代码?
答案 0 :(得分:15)
是的,要调用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,以便将所有内容链接在一起。
答案 1 :(得分:1)
我对elmarco的回答唯一的补充是extern
关键字。如果您正在尝试访问已在其中一个软件包或标准C / Posix库中使用的单个C函数,则可以通过这种方式轻松访问它。
答案 2 :(得分:1)
对于用C编写的基于GLib的库,您可以尝试从C源生成gir文件:Vala/Bindings。
手动操作也没问题。假设您有一个库,它在C中定义SomelibClass1,并使用一个名为do_something的方法,该方法接受一个字符串。 头文件的名称是&#34; somelib.h&#34;。然后相应的vapi就像下面这样简单:
somelib.vapi:
[CCode (cheader_filename="somelib.h")]
namespace Somelib {
public class Class1 {
public void do_something (string str);
}
}
可以在此处找到为非GLib库编写vapis的文档:Vala/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中的名称。
这个主题还有很多,但这应该给你一个概述。
答案 3 :(得分:-1)
从c访问您的vala代码可能更容易。所有你需要做的就是编译成C。