2010-03-23 8 views
11

Ich würde gerne ein bestehendes GLib-basiertes C-Projekt mit Vala hacken.Vala vapi files documentation

Grundsätzlich, was ich tue, ist am Anfang meines Build-Prozesses, Valac zu verwenden, um .c und .h-Dateien aus meinen .vala-Dateien zu generieren und dann nur die generierten Dateien so wie ich c oder .h-Datei.

Dies ist wahrscheinlich nicht der beste Weg, aber scheint in den meisten Fällen in Ordnung zu sein.

Mein Problem ist, dass es mir schwer fällt, auf meinen vorhandenen C-Code von meinem Vala-Code zuzugreifen. Gibt es einen einfachen Weg, dies zu tun?

Ich habe versucht, meine eigenen .vapi-Dateien zu schreiben (ich hatte kein Glück mit dem Tool, das mit Vala kam), aber ich kann keine anständige Dokumentation finden, wie man diese schreibt.

Gibt es irgendwelche? Benötige ich eine dieser Dateien, um vorhandenen C-Code aufzurufen?

Antwort

15

Ja, um eine C-Funktion aufzurufen, müssen Sie eine Bindung dafür schreiben. Der Prozess ist in http://live.gnome.org/Vala/Tutorial#Binding_Libraries_with_VAPI_Files beschrieben, dies gilt jedoch nicht direkt für benutzerdefinierte Funktionen oder Bibliotheken, die ohne GObject geschrieben wurden. Wenn Sie eine komplexe Bindung für Nicht-GObject-Bibliotheken haben, benötigen Sie wahrscheinlich Hilfe vom #vala-IRC-Kanal.

Die meiste Zeit benutzen wir jedoch einfache vapi-Dateien, um einige autoconf-Define oder einige Funktionen zu schreiben, die in plain C geschrieben sind, aus Gründen der Effizienz oder gebrochenen Vala oder aus irgendeinem anderen Grund. Und das ist die Art und Weise, dass die meisten Menschen tun:

myfunc.vapi

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

myfunc.h (und entsprechende Implementierung in einer .c mit Ihrem Projekt verknüpft)

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

example.vala könnte

using MyFunc; 

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

Wenn mit valac Kompilieren verwenden --vapidir= das Verzeichnis lo zu geben Kation der myfunc.vapi. Abhängig von Ihrem Build-System müssen Sie möglicherweise ein zusätzliches Argument an valac oder gcc CFLAGS übergeben, um alles miteinander zu verknüpfen.

+0

Danke! Ein Problem, das ich habe ist, dass, wenn ich die Header-Datei in myfunc.vapi angeben, schreibt die .c-Ausgabe von ValaC#include , wenn was ich wirklich will ist #include "myfunc.h". Irgendeine Idee, wie man das löst? Ist es lösbar? – Jordan

+0

Dies sollte keine große Sache sein, solange die Datei nicht in Ihrem System-Include installiert ist, wird sie in Ihrem Projektverzeichnis geöffnet, wenn Sie den Pfad mit -I .. angeben (Beispiel: -I $ (topsrc_dir)/libfoo) – elmarco

1

Der einzige Zusatz, den ich zu Elmarcos Antwort machen würde, ist das Schlüsselwort extern. Wenn Sie versuchen, auf eine einzelne C-Funktion zuzugreifen, die bereits in einem Ihrer Pakete oder den Standard-C/Posix-Bibliotheken verfügbar ist, können Sie auf diese Weise leicht darauf zugreifen.

-1

Es wäre wahrscheinlich einfacher, einfach auf Ihren vala-Code von c zuzugreifen. Sie müssen lediglich nach C kompilieren.

1

Für in C geschriebene GLib-basierte Bibliotheken können Sie versuchen, gir-Dateien von Ihren C-Quellen zu generieren: Vala/Bindings.

Manuell machen ist auch kein Problem. Angenommen, Sie haben eine Bibliothek, die SomelibClass1 in C mit einer Methode namens do_something definiert, die eine Zeichenfolge verwendet. Der Name der Headerdatei lautet "somelib.h". Dann ist das entsprechende vapi so einfach wie das folgende:

somelib.vapi:

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

Dokumentation zum Schreiben vapis für Nicht-GLib Bibliotheken finden Sie hier: Vala/LegacyBindings

Dies ist eigentlich wirklich einfach ist. Lets von posix.vapi einen Ausschnitt nehmen:

[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); 
} 

Dies implementiert die folgende C-Funktion:

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

Wenn die instance_pos Verwerfen Attribut vala nimmt an, dass das Objekt sich auf ein Verfahren der erste Parameter ist. Auf diese Weise können C-Konstrukte, die in etwa objektorientiert sind, gebunden werden. Die Methode free_method der Klasse compact wird aufgerufen, wenn das Objekt dereferenziert wird.

Die BuKr (cname) -Attribut einer Methode, Klasse, Struktur hat usw. der Name es sein, wie es in C wäre

viel gibt mehr zu diesem Thema, aber das sollte Ihnen einen allgemeinen Überblick geben.

+0

Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz zur Verfügung zu stellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. –

+0

danke für den Hinweis. Ich habe meine Antwort bearbeitet. – Richard