11

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

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

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

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

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

有吗?我需要这些文件之一来调用现有的 C 代码吗?

4

4 回答 4

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 以便将所有内容链接在一起。

于 2010-03-24T23:12:46.040 回答
1

我要对 elmarco 的回答做的唯一补充是extern关键字。如果您尝试访问某个包或标准 C/Posix 库中已经提供的单个 C 函数,您可以通过这种方式轻松访问它。

于 2010-11-03T00:12:18.933 回答
1

对于用 C 编写的基于 GLib 的库,您可以尝试从 C 源代码生成 gir 文件:Vala/Bindings

手动操作也没问题。假设您有一个库,该库在 C 中定义 SomelibClass1,其中包含一个名为 do_something 的方法,该方法接受一个字符串。头文件的名称是“somelib.h”。那么对应的vapi就简单如下:

一些lib.vapi:

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

可以在此处找到为非 GLib 库编写 vapi 的文档: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 结构。当对象被取消引用时,紧凑类的 free_method 被调用。

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

这个主题还有很多内容,但这应该会给你一个大致的概述。

于 2014-04-13T09:09:28.237 回答
-1

仅从 c 访问您的 vala 代码可能会更容易。因为你所要做的就是编译成C。

于 2010-12-24T09:18:42.083 回答