SQLite + Vala

Um dos efeitos colaterais do último post (e da insônia) foi que descobri porque não estava conseguindo usar os bindings Vala pra API C de SQLite. Nela existe a função exec, usada para executar statements SQL, que recebe como parâmetro uma função callback a ser executada após o término da query.

A função sqlite3_exec

int
sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void*, char**);

A assinatura da função callback em C é:

typedef int
(*sqlite_callback) (void*, int, char**, char**);

E no binding para Vala:

public static int
callback(pointer data, int n_columns, string[] values, string[] column_names) {
(...)

Estava tentando portar o código deste tutorial, para Vala, mas mesmo compilando terminava em segfault, mas antes disso mostrava uns dados totalmente errados.

Como você sabe bem, o compilador valac pode gerar código C, basta não usar a cláusula “-o outfile“: valac --pkg sqlite3 simplesqlite.vala, e pronto, são criados simplesqlite.h e simplesqlite.c, em lugar do costumeiro executável. Fiz isso e olhe só o que estava gerando:

gint
demo_callback (gpointer data, gint n_columns, int values_length1, char** values, int column_names_length1, char** column_names) {
(...)

O problema é que o valac transforma arrays de Vala em arrays de C precedidos de um inteiro que informa seu tamanho. Você pode evitar esse comportamento avisando ao compilador da seguinte forma:

[NoArrayLength ()]
public static int
callback (pointer data, int n_columns, string[] values, string[] column_names) { (...)

Passei um tempinho até descobrir isso (a documentação de Vala está nas fases iniciais de produção), tentei [NoArrayLength], mas resultava em char**, precedido de int, mas este era setado para -1. Cheguei a relatar um bug (487612), mas já corrigi a gafe.

Cairo + Vala

Resolvi gastar 1 das minhas 5 horas de sono diárias para dar uma mexida no binding Vala pra biblioteca de gráficos vetoriais Cairo.

Minha idéia era portar algo pronto em outra linguagem, então peguei um exemplo interessante do binding Python PyCairo. Com as anotações do PyCairo informando quais tipos eram passados como parâmetro, ficou mais fácil que mastigar água de cabeça pra baixo. Em alguns momentos eu só acrescentei ponto-e-vírgula ao fim das linhas de código Python.

Cairo Vala Demo
Cairo desenhando sobre uma Gtk.DrawingArea
(Dublin ao fundo)

Faz um bom tempo que estou no regime Python & C, e estava perdendo o traquejo de como programar numa linguagem orientada a objetos com tipagem estática, por isso Vala está sendo algo bastante útil, além de divertido.

Uma das coisas que eu não estava sabendo fazer era passar um array de double como parâmetro para esta função da classe Context do módulo Cairo:

public void set_dash (double[] dashes, int num_dashes, double offset);

A solução:

ctx.set_dash (new double[] {SIZE / 4.0, SIZE / 4.0}, 2, 0);

E a forma a qual eu estava (mal ;) ) acostumado em Python:

ctx.set_dash([SIZE/4.0, SIZE/4.0], 0)

Coloquei como exemplo na wiki do Vala, e o arquivo pode ser baixado aqui: cairo-demo.vala.

Maemo SDK Appliance, release 0.2

Time for a new release of the Maemo SDK Appliance. And now it comes with Chinook! See the release notes:

This version features the Maemo 4.0 (Chinook) Beta environment, along with Vala compiler and its Hildon bindings, and some samples (in C and Vala).

Yes! It is true, we at INdT are atrociously bleeding edge! We have installed Vala compilers for i386 and armel targets, and some examples also. Look at the sweetness:

using GLib;
using Gtk;
using Hildon;
public class Example1 : Hildon.Window
{
[Widget] protected Label label1;
[Widget] protected Button button1;
construct {
label1 = new Label("Don't press the button!");
button1 = new Button.from_stock("gtk-no");
button1.set_size_request(-1, 100);
button1.clicked += btn => {
label1.label = "I told you not to press the button!";
};
...
}

Watch the movie:

And download the torrent from PirateBay (yarrr!).

Almost forgot, we have a mailing list: maemovmware-users

Pacote Debian do Vala

Hoje Alberto Ruiz (que parece assustadoramente com um amigo meu; alô Icaro!) fez um binding Vala pro GtkMozEmbed, daí me empolguei e fiz um pacote Debian do bicho. Estava num Ubuntu Gutsy e não testei em nenhuma outra máquina, então só garanto funcionar do Gutsy pra cima (dica: precisa libglib maior igual a 2.12.9).

Download: vala_0.1.2-1_i386.deb

Se quiser experimentar uns códigos (com um esclarecedor Makefile), veja o post anterior sobre Vala.

Já criei um binding pro Hildon que deve deixar os manos do INdT felizes, só falta arrumar uma coisa e outra e mando o patch.

Vala para Mobile with Lasers, digo, com Figuras

O mesmo que falei antes, agora com figuras! (Porque sem figuras fica chato.)

O primeiro diagrama mostra um cenário com Mono sendo usado como plataforma de desenvolvimento para portáteis, o diagrama seguinte mostra o equivalente em Vala.

Mono foi escolhido como exemplo por Vala ser fortemente inspirada em sua sintaxe, e também por uma discussão na lista mobile-devel do GNOME, onde alguém pergunta o motivo de Mono não estar sendo considerado e dentre as resposta está uma de Jeff Waugh que diz: “Mono is a can of worms that no one really wanted to open”. (Leia o resto pra não tirar conclusões precipitadas.)

Não estou aqui desconsiderando os módulos/bibliotecas e outras coisas que vem junto com o Mono, esta é um comparação um tanto grosseira.

Mono_for_mobile
Mono: menos passos para compilação, mais peso no runtime.

Vala_for_Mobile
Vala: mais passos para compilação, mas o runtime nem precisou saber…

Vala para Mobile

Como você já deve saber, o sistema de tipos e orientação a objetos de GTK+ é baseado na GLib. E como você já deve saber, botar pra funcionar orientação a objetos em C é um troço bem engenhoso, mas muito doido e cansativo. Daí que boa parte dos programas em GTK+ é escrita em linguagens de alto nível usando bindings (PyGTK, GTK#, gtkmm, java-gnome).

Os bindings são muito úteis, mas para um programa feito em PyGTK funcionar, é necessário ter instalados em seu sistema GTK+, Python e PyGTK. Num sistema Linux regular tudo isso já está lá e ninguém percebe. Já numa máquina Windows pode ser um pouco demais pedir pra o usuário instalar esses mondrongos antes do seu programa de 800kb. O problema no desktop não é falta espaço em disco ou memória, e sim evitar importunar o usuário com a instalação de dependências que ele não precisa saber que existem. (Tem gente trabalhando nesse último problema.)

Mas o que me motivou a escrever esse post foram os sistemas móveis. Já temos uma certa quantidade de plataformas móveis baseadas em GTK+ (e GStreamer, e outras GLib-coisas): Maemo, OpenMoko, OLPC. Bindings para linguagens de alto nível estão normalmente disponíveis e sua instalação costuma ser transparente para o usuário. Só não é transparente para os recursos limitados do dispositivo portátil, mas pedir aos desenvolvedores que usem GLib-C[1] certamente não vai te tornar um cara mais popular.

Vala

Vala é uma linguagem com sintaxe próxima de C#, com algumas adaptações para se encaixar melhor no sistema de tipos do GObject. Pelo menos é isso que diz no site. Já a wikipedia diz o seguinte:

Vala (valá-), meaning “enclosure” in Vedic Sanskrit, is an Asura of the Rigveda and the Atharvaveda, the brother of Vrtra.
(…)
Historically, it has the same origin as the Vrtra myth, being derived from the same root, and from the same root also as Varuna, *val-/var- (PIE *wel-) “to cover, to enclose” (perhaps cognate to veil).

Wikipedia: Vala (Vedic)

Antes de você começar a pensar que se trata de mais um binding pra GTK+, vou esclarecer que a saída gerada pelo compilador Vala é nada menos que código GLib-C, que pode ser compilado normalmente pelo GCC para binários nativos, linkando diretamente com bibliotecas baseadas na glib. Vala é algo que, fazendo uma analogia ao asura do mito védico, cobre/envolve o código GLib-C, ocultando sua complexidade. A ligação Vala-C é feita por um arquivo .vapi, que, como cansei de dizer, só é necessário em tempo de compilação.

Voltando ao cenário dos dispositivos móveis, com Vala o desenvolvedor tem o conforto equivalente a um binding de alto nível, e o portátil não tem de pagar o preço por isso. Abstração sem overhead!

Instalando

Pegue a versão mais recente em http://live.gnome.org/Vala/Release e compile da maneira usual. Além das ferramentas de praxe, Bison e Flex precisam estar instalados (no Debian/Ubuntu são os pacotes bison e flex).

Comparação

Vejamos um código bem simples em Vala, apenas uma classe que herda de um GObject e acrescenta um campo de texto.

// example.vala
using GLib;
public class MyObject : Object
{
protected string text { get; set; }
public MyObject () {
text = "";
}
}

Para gerar o código C (.h e .c), chame: valac example.vala

Os get e set da linha abaixo

protected string text { get; set; }

dão origem a

char* my_object_get_text (MyObject* self)
{
g_return_val_if_fail (IS_MY_OBJECT (self), NULL);

return self->priv->_text;
}

void my_object_set_text (MyObject* self, const char* value)
{
g_return_if_fail (IS_MY_OBJECT (self));

char* __temp2 = NULL;
const char* __temp1 = NULL;
self->priv->_text = (__temp2 = (__temp1 = value, (__temp1 == NULL ? NULL : g_strdup (__temp1))), (self->priv->_text = (g_free (self->priv->_text), NULL)), __temp2);
}

Mais Código

Como este blog honra as calças que veste, os seguintes códigos de exemplo (junto com um Makefile) podem ser encontrados no svn do google:

Minha intenção é gerar os bindings pra algumas coisas interessantes como tapioca-glib e hildon. Pode levar um tempo, mas assim que estiver pronto posto algo.

[1] GLib-C é a forma como Steven Hendrickx se refere a código C escrito no estilo orientado a objetos da GLib em seu texto Glib-C: C as an alternative Object Oriented Environment.