This is how we generate the Vala bindings for poppler-glib. Note that you can only bind GLib-based APIs with the .gi format, for other C libraries you will have to stick to writing vapi manually.

The following example demonstrates how to write poppler-glib bindings for Vala. Poppler has a GLib wrapper, and we're going to use it to generate our own Vala API.

$ vala-gen-introspect
Usage: vala-gen-introspect PKGNAME BASEPATH

vala-gen-introspect, the command responsible to generate our .gi interfaces, needs the package development files to be installed.

$ mkdir poppler-glib
$ ls
poppler-glib

Now, we proceed to generate the gi files:

$ vala-gen-introspect poppler-glib poppler-glib
cat: poppler-glib/poppler-glib.files: No such file or directory
cat: poppler-glib/poppler-glib.namespace: No such file or directory
ERROR: Need at least one header file.

Oops! What's going on here? Let's figure it out... two things are wrong here:

First, it seems that it lacks some filename (poppler-glib.files and poppler-glib.namespace) /!\ NOTE: The package name (PKGNAME argument) has to be the same as the pkg-config package file (.pc) of the original library.

vala-gen-introspect is not a so magical tool (yet), you need to provide a list of directories where the glib/gobject source files are stored inside the package and the namespace to populate those files (package.files and package.namespace), the namespace is the prefix used in the functions and struct names.

How do we figure this out? We need to take a look at the headers:

First we figure out the pkg-config package name:

$ ls /usr/lib/pkgconfig/ | grep poppler
poppler-cairo.pc
poppler-glib.pc
poppler.pc
poppler-splash.pc

So, poppler-glib is the one we were looking for since it's the library that we're going to bind. Now we need to figure out where the poppler-glib headers and libraries are, in order to populate poppler-glib.files. This file is going to have all the directories with gobject headers and libraries:

$ grep Cflags /usr/lib/pkgconfig/poppler-glib.pc
Cflags: -I${includedir}/poppler/glib
$ ls /usr/lib/libpoppler*.so
/usr/lib/libpoppler-glib.so  /usr/lib/libpoppler.so

$(prefix)/include/poppler/glib/ seems a good candidate, isn't it? Okay, now the namespace, that's pretty easy, we only need to look inside some header file, for example, glib/poppler.h:

$ grep 'typedef struct' /usr/include/poppler/glib/poppler.h
typedef struct _PopplerDocument    PopplerDocument;
typedef struct _PopplerIndexIter   PopplerIndexIter;
typedef struct _PopplerFontsIter   PopplerFontsIter;
...

So it seems that the prefix used as source namespace is Poppler, we're ready to generate the .gi file. Remember, we use now the package name for the .files and the .namespace file, and we have to include it after the path:

poppler-0.5.4 $ cd ..
$ echo "include/poppler/glib/" > poppler-glib/poppler-glib.files
$ echo "lib/libpoppler-glib.so" >> poppler-glib/poppler-glib.files
$ echo "Poppler" > poppler-glib/poppler-glib.namespace
$ vala-gen-introspect poppler-glib poppler-glib
Unknown symbol: GObject
Unknown symbol: GObject

$ ls poppler-glib/
poppler-glib.files  poppler-glib.gi  poppler-glib.namespace

So that's it, we've generated our first .gi file!

Projects/Vala/Bindings/GI (last edited 2013-11-22 16:48:30 by WilliamJonMcCann)