Документация файлов Vala vapi

Я хотел бы взломать существующий проект на основе GLB, используя Vala.

В основном то, что я делаю, это в начале моего процесса сборки, используя valac для генерации файлов .c и .h из моих .vala файлов, а затем просто компилировать сгенерированные файлы так, как если бы я был .c или. h файл.

Это, вероятно, не самый лучший способ, но, похоже, работает в основном по большей части.

Моя проблема в том, что мне трудно получить доступ к существующему коду C из моего кода Vala. Есть простой способ сделать это?

Я пробовал писать свои собственные .vapi файлы (мне не повезло с инструментом, который поставлялся с vala), но я не могу найти достойную документацию о том, как их писать.

Есть ли какие-либо существуют? Нужен ли мне один из этих файлов для вызова существующего кода C?

Ответ 1

Да, чтобы вызвать функцию C, вам нужно написать привязку для нее. Процесс описан в http://live.gnome.org/Vala/Tutorial#Binding_Libraries_with_VAPI_Files, однако это не относится непосредственно к пользовательским функциям или библиотекам, написанным без GObject. Вам, вероятно, понадобится помощь от #vala IRC-канала, если у вас есть сложная привязка для библиотек, отличных от GObject.

Однако большую часть времени мы используем простые файлы vapi для привязки некоторого определения autoconf или некоторых функций, написанных на простой C, по соображениям эффективности или сломанной вале, или по какой-либо другой причине. И так поступает большинство людей:

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, чтобы связать все вместе.

Ответ 2

Единственное дополнение, которое я сделал бы для ответа elmarco, - это ключевое слово extern. Если вы пытаетесь получить доступ к одной функции C, которая уже доступна в одном из ваших пакетов или в стандартных библиотеках C/Posix, вы можете легко получить доступ к этому пути.

Ответ 3

Для библиотек на основе GLib, написанных на C, вы можете попытаться генерировать gir файлы из ваших C-источников: Vala/Bindings.

Выполнение этого вручную тоже не проблема. Предположим, у вас есть библиотека, которая определяет SomelibClass1 в C с помощью метода do_something, который принимает строку. Имя заголовочного файла - "somelib.h". Тогда соответствующие vapi просты, чем следующие:

somelib.vapi:

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

Документацию для написания vapis для библиотек, отличных от GLib, можно найти здесь: 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_mode компактного класса вызывается, когда объект разыменовывается.

CCode (cname) -трибут метода, класса, структуры и т.д. должен быть его именем, как это было бы в C.

В этом вопросе гораздо больше, но это должно дать общий обзор.

Ответ 4

Вероятно, было бы проще просто получить доступ к вашему vala-коду из c. Поскольку все, что вам нужно сделать, это просто скомпилировать с помощью C.