Friday, 16 April 2010

Claudia black makes this look good

OK maybe the title is a bit of a reach, but she is pretty and my topic is dull.

It is the school holidays and between entertaining the kids I have been experimenting with the vala (see there is the link to the title) language. Overall I really like it, building a usable graphical GTK application is a snap and that side of it works well.

Unfortunately, and here comes a a whole pile of fail, the documentation is lacking, not just poor but mostly non-existent. You rapidly discover yourself using the Glib and GTK library documentation to try and infer how things work.

Underneath, the vala compiler is clever, it is really a c code generator. It takes your vala source file converts it to c and compiles it. When it works smoothly it works very well, when something is not quite right you can end up with a large pile of pieces complete with the C compiler spitting out cryptic nonsense.

This is all exasperated to new heights of madness when you want to access a simple c library. I say simple because if you want to access a Glib based library its easy and "there is an app for that". Because vala is object oriented c interfaces must be described as an object. This description is performed using vapi files. The file format is documented by the simple approach of "we already wrapped a load of libs go look at their vapi files"

For my small starter project I wanted to access a tiny c library I had written. The entire interface described in a single header header (excluding copyright) is:
typedef enum motor_dir {
motor_off = 0,
motor_forward = 1,
motor_back = 2,
motor_brake = 3,
} motor_dir;

int edgerbtarm_init(void);
int edgerbtarm_close(void);
void edgerbtarm_ctrl_motor(int motorn, motor_dir direction);

Yes that is it! one enum, an initialise a finalise and a single operation function. The vapi file I came up with after a great deal of trial, error and head scratching was.
[CCode(cheader_filename = "libedgerbtarm.h",
lower_case_cprefix = "edgerbtarm_",
cprefix = "")]
namespace edgerbtarm {
[CCode(cprefix = "motor_")]
public enum motor_dir {
off,
forward,
back,
brake
}

public int init();
public int close();
public void ctrl_motor(int motorn, motor_dir direction);
}
This seemed to work until I tried to use the motor_dir type within my vala code at which point the c compiler started throwing errors about undeclared macros
arm.vala.c:297: error: ‘EDGERBTARM_TYPE_MOTOR_DIR’ undeclared (first use in this function)
I struggled for some time and finally ended up asking my friend Enrico for help. He initially suggested I simply use an int instead of the motor_dir type and cast when I needed to. This approch worked and let me compile the program, it did however seem a bit grubby and removed the type safety of the enum.

Then Enrico came up with the "correct" solution. the enum description in the in the vapi file needed an extra parameter so vala would know the enum did not have a Glib type...yeah it was obvious to me too :-/

so by altering the vapi file enum declaration to
[CCode(cprefix = "motor_", has_type_id = false)]
public enum motor_dir {
off,
forward,
back,
brake
}
Everything works as you might expect and the motor_dir enum can be used as a type within the vala program with no more fuss.

So the outcome of all this is that while vala is an interesting language which I may well use again in future, one should be aware that it is still very immature as a solution and has nowhere near enough documentation especially round the awkward stuff where it needs it most.

2 comments:

  1. I don't understand one word of that but if you think of the character "Vala" it kind of fits...seems like you're having troubles...

    Yes, the name Claudia Black caught my eye. She is fabulous.

    ReplyDelete