sexta-feira, 13 de agosto de 2010

Programação de GUIs utilizando GTK - Parte 2

.
Neste post vamos tratar da montagem do ambiente para programação GTK, exemplificando através de uma distribuição Ubuntu, versão 10.04 (GNU/Linux), recém instalada. Os requisitos para acompanhar este e os próximos posts são: conhecimentos (nível intermediário) da linguagem C (incluindo ponteiros), geração de arquivos-fonte e sua compilação pela linha de comando (terminal) utilizando o GCC.

Vamos começar com um programa simples, baseado em GTK+, uma espécie de "Hello World" dos programas em ambiente gráfico: mostra uma janela vazia na tela. O código segue abaixo:

 #include <gtk/gtk.h>
int main (int argc, char *argv[])
{
GtkWidget *window;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Alou, Mundo!!!");
gtk_widget_show (window);
gtk_main ();
return 0;
}

Não se preocupe com os detalhes do programa, veremos isso depois. O objetivo agora é apenas conseguir compilar e executar o dito cujo, pelo terminal. Gere um arquivo-fonte em C com o código acima, digamos, aloumundo.c, e tente compilar:

gcc -o aloumundo aloumundo.c

E receba um monte de mensagens de erro... :-)

 aloumundo.c:2:21: error: gtk/gtk.h: No such file or directory
aloumundo.c: In function ‘main’:
aloumundo.c:6: error: ‘GtkWidget’ undeclared (first use in this function)
aloumundo.c:6: error: (Each undeclared identifier is reported only once
aloumundo.c:6: error: for each function it appears in.)
aloumundo.c:6: error: ‘window’ undeclared (first use in this function)
aloumundo.c:10: error: ‘GTK_WINDOW_TOPLEVEL’ undeclared (first use in this function)

Bom, a coisa começa pelo fato de que o compilador não encontrou a biblioteca gtk (personificada, digamos assim, neste exemplo, pelo arquivo gtk.h). E a partir daí, nada relacionado com gtk foi interpretado.

O que acontece é que, apesar de estarmos usando um ambiente gráfico baseado em GTK (Gnome), ou seja, a biblioteca gtk está garantidamente instalada no sistema, precisamos instalar a biblioteca PARA DESENVOLVIMENTO. Em sistemas baseados no Debian, acho que em 99% dos casos, bibliotecas para desenvolvimento tem seu nome terminado em -dev (em outras distribuições, este tipo de biblioteca tem seu nome terminado em -devel).

Abrimos o gerenciador de pacotes Synaptic, e procuramos por libgtk:



Descobrimos que o nome correto é libgtk2.0-dev. Ao marcarmos para instalação, o Synaptic automaticamente seleciona outros pacotes que também são requeridos. Na verdade, quando falamos em GTK estamos falando em um conjunto de bibliotecas, como por exemplo, GLib (funções utilitárias de propósito geral), GDK (camada entre o sistema gráfico X e GTK), Pango (textos e fontes), ATK (acessibilidade), entre outras.



Agora, com as bibliotecas instaladas, podemos tentar compilar novamente, e.... ué?!?!? Erro de novo?

Isso acontece porque precisamos indicar ao GCC que queremos utilizar uma biblioteca extra, além da biblioteca-padrão, que ele já sabe usar diretamente. Isso significa indicar os seguintes itens:

  • caminho para o diretório onde estão os "includes" da(s) biblioteca(s) que você quer usar. Isso é feito utilizando-se a opção -I (letra "i" maiúscula);
  • caminho para o diretório onde estão as bibliotecas a serem utilizadas. Isso é feito utilizando-se a opção -L (letra "l" maiúscula);
  • finalmente, quais bibliotecas serão utilizadas, com a opção -l (letra "l" minúscula). Nomes de bibliotecas começam pelas letras "lib" (por exemplo, libblabla), e utilizamos com -lblabla (o nome depois do lib).

Já falamos que GTK é composta de várias bibliotecas de suporte. Isso significa dizer que, para compilar usando GTK, teremos que informar ao compilador, usando as opções acima, diretórios e bibliotecas para todas elas. Felizmente, temos um programa que nos auxilia nisso, chamado pkg-config, retornando as informações necessárias, para um pacote/biblioteca específico. Como nos diz o comando man,

"The pkg-config program is used to retrieve information about installed libraries in the system. It is typically used to compile and link against one or more libraries."

Então vamos experimentar, digite no terminal:

pkg-config --cflags --libs gtk+-2.0

A opção --cflags diz para retornar informações acerca dos includes, e --libs para bibliotecas, tudo isso relativo ao pacote indicado no final da linha, "gtk+-2.0".

Você deve ter obtido a seguinte saída:

-pthread -D_REENTRANT -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/directfb -I/usr/include/libpng12 -pthread -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lrt -lglib-2.0

... ou seja, todos os parâmetros necessários para você compilar um programa que utilize a biblioteca GTK (e suas companheiras).

E como utilizamos isso? Copio essa coisa toda e digito junto com o comando de compilação, gcc?? Não precisa. Podemos simplesmente indicar ao GCC que os parâmetros de compilação vão ser informados pelo pkg-config. Fazemos isso dessa forma:

gcc -o aloumundo aloumundo.c `pkg-config --cflags --libs gtk+-2.0`

A linha acima tem o seguinte efeito: o comando pkg-config é executado, e sua saída é integrada ao resto da linha (compilação com o gcc) como se tivesse sido digitada normalmente. Agora, CUIDADO!! O caracter que envolve o pkg-config é a CRASE (não é a aspa simples, não é o acento agudo!).

Agora, você deve obter uma compilação sem erros, já que todas as bibliotecas estão instaladas no sistema, e você indicou ao compilador como usá-las.

Falta só executar sua obra-prima.... :-)

./aloumundo



Algumas observações finais:

  • se você clicar no 'X' para fechar a janela, ela fecha, mas o programa continua sendo executado (o terminal fica "travado"). Para liberar o terminal, precisamos finalizar o programa na marra, teclando CONTROL-C. Isso acontece porque o 'X' causa apenas a parte gráfica da coisa (a janela some da tela), mas não a finalização do programa. Isso é nossa responsabilidade, e veremos como fazer isso posteriormente.
  • note que você pode mover a janela, minimizar, maximizar, redimensionar.... como isso é possível, se não escrevemos código para isso? Isso é papo pro próximo artigo.

Abraços a todas e a todos!

Carlão

4 comentários:

Anônimo disse...

Muito bom o texto !
Entendi porque aqui não estava encontrando a biblioteca gtk.h

Eu usei o comando find para localizar o header e não achei rsrs

Valeu pelo dica, muito bem explicado.

[s]
Vitalino Victor

Marcos disse...

Cara parabéns pelo blog, mas só uma dúvida, estou construindo aplicações com glade para php-gkt2, a aplicação abre normalmente, porém sempre avisa esta mensagem:

Gtk-Message: Failed to load module "canberra-gtk-module": libcanberra-gtk-module.so: cannot open shared object file: Arquivo ou diretório não encontrado.

eu tenho a libcanberra-gtk-module.so na pasta /usr/lib/...

tenho de criar um link simbólico?como ?

abraços!

Carlos José Pereira disse...

Oi Marcos,

Não sei te responder com certeza, nunca vi esse erro. Mas uma dica, veja no gerenciador de pacotes da sua distribuição (se for ubuntu, use o synaptic), veja se a biblioteca libcanberra-gtk e outras com esse mesmo nome (talvez libcanberra-gtk-module) estão instaladas, em especial as que terminam com -dev (para desenvolvimento).
Vou tentar dar uma pesquisada adicional, pra ver se acho alguma coisa.
Abraços!
Carlão

Ira disse...

This is cool!