2010-03-23 9 views
11

Mi piacerebbe hackerare un progetto esistente basato su GLib utilizzando Vala.Documentazione file Valap vapi

Fondamentalmente quello che sto facendo è, all'inizio del mio processo di compilazione, l'uso di valac per generare file .c e .h dai miei file .vala e quindi semplicemente compilare i file generati come farò con qualsiasi .c o .h file.

Questo probabilmente non è il modo migliore, ma sembra funzionare per la maggior parte.

Il mio problema è che sto avendo difficoltà ad accedere al mio codice C esistente dal mio codice Vala. C'è un modo semplice per farlo?

Ho provato a scrivere i miei file .vapi (non ho avuto fortuna con lo strumento fornito con vala), ma non riesco a trovare alcuna documentazione decente su come scriverli.

Esiste? Ho bisogno di uno di questi file per chiamare il codice C esistente?

risposta

15

Sì, per chiamare una funzione C, è necessario scrivere un'associazione per esso. Il processo è descritto in http://live.gnome.org/Vala/Tutorial#Binding_Libraries_with_VAPI_Files, tuttavia, questo non si applica direttamente alle funzioni personalizzate o alle librerie scritte senza GObject. Probabilmente avrai bisogno di aiuto dal canale IRC#vala se hai un binding complesso per le librerie non-GObject.

Tuttavia, la maggior parte delle volte, utilizziamo semplici file vapi per associare alcune definizioni di autoconf o alcune funzioni scritte in plain C, per ragioni di efficienza o vala spezzate, o qualsiasi altra ragione. E questo è il modo in cui la maggior parte delle persone lo fanno:

myfunc.vapi

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

myfunc.h (e corrispondente implementazione in un .c collegato con il progetto)

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

example.vala potrebbe essere

using MyFunc; 

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

Quando si compila con valac, utilizzare --vapidir= per dare la lo directory catione di myfunc.vapi. A seconda del sistema di compilazione, potrebbe essere necessario passare argomenti aggiuntivi a valac o gcc CFLAGS per collegare tutto insieme.

+0

Grazie! Un problema che sto avendo è che quando specifico il file header in myfunc.vapi, l'output .c di valac scrive #include quando quello che voglio veramente è #include "myfunc.h". Qualche idea su come risolvere questo? È risolvibile? – Jordan

+0

questo non dovrebbe essere un grosso problema, finché il file non è installato nel tuo sistema include, sarà aperto nella directory del tuo progetto, se fornisci il percorso con -I .. (esempio: -I $ (topsrc_dir)/libfoo) – elmarco

1

L'unica aggiunta che farei alla risposta di elmarco è la parola chiave extern. Se stai cercando di accedere a una singola funzione C già disponibile in uno dei tuoi pacchetti o alle librerie standard di C/Posix, puoi accedervi facilmente in questo modo.

-1

Probabilmente sarebbe più semplice accedere al tuo codice Vala da c. Come tutto quello che devi fare è compilare semplicemente C.

1

Per le librerie basate su GLib scritte in C puoi provare a generare gir-files dalle tue sorgenti C: Vala/Bindings.

Anche farlo manualmente non è un problema. Supponiamo di avere una libreria che definisce SomelibClass1 in C con un metodo chiamato do_qualcosa che prende una stringa. Il nome del file di intestazione è "somelib.h". Quindi il corrispondente vapi è semplice come il seguente:

somelib.Vapi:

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

Documentazione per la scrittura vapis per le librerie non GLib può essere trovato qui: Vala/LegacyBindings

Questo è in realtà molto semplice. Facciamo un estratto 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); 
} 

Questo realizza la seguente C-Function:

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

Quando scartando i instance_pos attributo vala presuppone che l'oggetto è il primo parametro a un metodo. In questo modo è possibile associare i costrutti c che sono approssimativamente orientati agli oggetti. Il metodo free_method della classe compatta viene chiamato quando l'oggetto è dereferenziato.

Il CCODE (CNAME) -attribute di un metodo, di classe, struct, ecc deve essere il nome di essa come sarebbe in C.

C'è molto di più a questo tema, ma questo dovrebbe darti una panoramica generale

+0

Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il link per riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. –

+0

grazie per il suggerimento. ho modificato la mia risposta. – Richard