Wednesday, September 7, 2011

Brüken bauen - Using vala code from JavaScript

Police bridge

GObject based libraries can be called - thanks GObject introspection - quite easy from javascript (as well as e.g. python).
As vala builds on gobject, all code generated by vala can be introspected - when compiled with a fine selection of compiler switches.

Let's pretend that we have got a small library written in vala and want to use it from gjs - maybe because the that library is wrapping another non-gobject library or doing some heavy calculations.

To build a introspectable library a good practice is, to just use valac to generate the appropriate c-code and handle the build manually - or by using some build system.
When invoking valac it is important to pass the two both of switches --library and --gir. It is also important to specify the GIR name (--gir) in the format NAME-VERSION.gir whereas the library (--library) name expects just NAME-VERSION.

Build
Up to now it's just theory. The following lines guide you trough this process, step by step (testShared.vala is taken from here):
$ ls
testShared.vala

$ valac --ccode --header=testShared.h \
   --gir=TestShared-0.1.gir \
   --library=TestShared-0.1 \
   --pkg=gio-2.0 testShared.vala

$ ls
TestShared-0.1.gir  TestShared-0.1.vapi
testShared.c testShared.h
testShared.vala

$ gcc -fPIC -shared -o libTestShared.so \
   $(pkg-config --libs --cflags gobject-2.0) \
   testShared.c 

$ ls *.so
libTestShared.so
 

Typelib
After building the library we finally need to build the introspection data using g-ir-compiler (part of gobject-introspection-devel):
$ g-ir-compiler --shared-library=libTestShared.so \
   --output=TestShared-0.1.typelib TestShared-0.1.gir
$ ls *.gir *.typelib
TestShared-0.1.gir
TestShared-0.1.typelib

Testing
To finally test our introspectable data, why use gjs. We import the library using the (gjs specific) "imports.gi" keyword:
const TestShared = imports.gi.TestShared;
print('Square of 42: ' + TestShared.square (42));
On the commandline it looks like this:
$ GI_TYPELIB_PATH=. LD_LIBRARY_PATH=. \
   gjs --command="const TestShared = imports.gi.TestShared; \
   print('Square of 42: ' + TestShared.square (42));"
** (gjs:12175): DEBUG: Command line: gjs
** (gjs:12175): DEBUG: Creating new context to eval console script
Square of 42: 1764
$

Done. We managed to call a library function from gjs using GObject introspection. The creation of the (important) typelib should be included in you favorite build tools, one example using cmake can be found (again) here.

Oone final reminder: Not just vala code can be imported, but all gobject based libraries (e.g. libgtop2 for system informations, clutter for fancy UIs and more)

Is there something I forgot? Tell me :)



No comments:

Post a Comment