quinta-feira, 19 de março de 2009

Sobre APIs

Umas das coisas mais importantes em programação, sem a qual ninguém consegue desevolver, é API.

API – Interface de Programação de Aplicativos – é o conjunto de recursos de que o programador dispõe para desenvolver suas aplicações.

Este artigo faz uma comparação – na verdade, mais uma demonstração – de cinco APIs muito usadas: IEEE 1003, STL, OpenStep, GLib e Java.

Para a demonstração será usado um trecho de código para ler a primeira linha de um arquivo.

Por que não a API do Windows?


Antes de começar, é preciso esclarecer por que não a API do Windows.

O objetivo de uma API é oferecer um ambiente homogêneo de programação, para que o programador não seja obrigado a reaprender a mesma coisa diversas vezes. Para facilitar isso, muitas APIs ainda podem ser usadas em diversas linguagens diferentes, outras em apenas uma.

No entanto uma API que funciona apenas em um único sistema operacional – ou ainda no grupo de sistemas operacionais de uma única empresa – não está fazendo seu trabalho, por mais usado que esse(s) sistema(s) possa ser.

Assim a API do Windows não faz mais do que se espera da interface de um sistema operacional.

É claro que é necessário que o Windows possua uma API, mesmo que seja exclusivamente para conexão de outras APIs mais universais.

IEEE 1003 (POSIX)


O padrão POSIX, definido pela IEEE, oferece uma interface completa para sistemas compatíveis com UNIX. Alguns exemplos são IBM AIX, Solaris, GNU (e daí também Linux), BSD, Mac OS X, MS Xenix e muitos outros.

O trecho de código em C para ler a primeira linha de um arquivo:
FILE *fd = fopen(filename, "r");

if (fd) {
while (!eof(fd)) {
char buf;
fread(&buf, sizeof(char), 1, fd);
printf("%c", buf);
if (buf == '\n')
break;
}

fclose(fd);
}


Observação1: é preciso incluir o cabeçalho stdio.h ou, em C++, cstdio:
#include <stdio.h>


Observação2: a variável filename é do tipo const char *.

Observação3: foi preciso procurar ocorrência do carácter \n pois POSIX não ofereça uma função de alto nível para ler uma linha.

Observação4: o padrão POSIX é completamente procedimental – as demais APIs citadas aqui são orientadas a objetos –, sendo um pouco desajeitado para algumas operações.

STL


A linguagem de programação C++ possui uma biblioteca padrão própria bastante completa chamada STL – Standard Library.

Para o exemplo, é preciso incluir o cabeçalho fstream para a manipulação de arquivo e o cabeçalho iostream para a exibição dos dados na tela:
std::ifstream fd(filename);

if (fd.is_open()) {
char buf[1024];
fd.getline(buf, 1023);

std::cout << buf << std::endl;
fd.close();
}


Observação1: como citado acima, é preciso incluir pelo menos o cabeçalho fstream ao manipular arquivos:
#include <fstream>


Observação2: a variável filename precisa ser do tipo const char *std::ifstream não suporta std::string.

OpenStep


A empresa NeXT de Steve Jobs, ora adquirida pela Apple, abriu a API de seu sistema operacional em 1992 num acordo com a SUN Microsystems, sob o nome de OpenStep, o que permitiu, além da criação de aplicações de terceiros para NeXTSTEP, também o desenvolvimento de outros sistemas operacionais compatíveis com sua API e APIs de programação para sistemas já existentes, tornando-os compatíveis com OpenStep.

Exemplos de sistemas compatíveis com essa API são Mac OS X e GNUstep (portável para Windows e qualquer plataforma compatível com POSIX).

A API OpenStep funciona exclusivamente em Objective-C, apesar de haver alguns portes para outras linguagens, como C++, Smalltalk e Guile Scheme.

Vamos ao exemplo em Objective-C:
id fd = [NSFileHandle fileHandleForReadingAtPath: filename];

if (fd != nil) {
char buf = 0;
[fd seekToEndOfFile];
unsigned long long eof = [fd offsetFile];
[fd seekToFileOffset: 0];

while (([fd offsetInFile] < eof) && (buf != '\n')) {
[[fd readDataOfLength: 1] getBytes: &buf length: 1];
printf("%c", buf);
}

[fd closeFile];
}


Observação1: é preciso importar o cabeçalho Foundation.h:
#import <Foundation/Foundation.h>


Observação2: a variável filename precisa ser do tipo NSString.

Observação3: eu não conheço um método para ler uma linha de um arquivo em OpenStep, portanto usei um esquema similar ao usado acima em POSIX.

GLib


A GLib começou como parte do toolkit gráfico Gtk+ na versão 2.0, tendo evoluído para se tornar uma API multiplataforma orientada a objetos completa e independente da interface gráfica.

Você pode usar GLib em qualquer sistema POSIX e em Windows.

A maior curiosidade da GLib é que ela deixa explícita o equívoco – ou a falácia – de quem crê que não seja possível programar orientado a objetos em uma linguagem não orientada a objetos: é escrita em C e completamente orientada a objetos.

Aliás a base da GLib é o GObject que, curiosamente, não é compatível com a estrutura de orientação a objetos de C++ e outras linguagens clássicas, apesar de haver portes para C++ e outras.

O exemplo a seguir é um trecho de código em Vala, linguagem criada expecificamente para a GLib:
var file = File.new_for_path(filename);

if (file.query_exists(null)) {
try {
var fd = new DataInputStream(file.read(null));
stdout.printf("%s\n", fd.read_line(null, null));
fd.close(null);
} catch (Error e) {
// Ignora exceções
}
}


[update 2009-03-19]Faltou o close.[/update]

Observação1: é preciso «usar» GLib:
using GLib;


Observação2: a variável filename é do tipo string – equivalente em C a GString e gchar *.

Observação3: é preciso usar o pacote (--pkg) gio-2.0, que importa GIO, recursos de I/O da GLib.

Java


Em sua linguagem de programação, a SUN Microsystems optou por criar uma API própria (bem complicada e verborrágica em relação às demais, diga-se).
BufferedReader fd = null;
try {
fd = new BufferedReader(new FileReader(filename));
System.out.println(fd.readLine());

} catch (Exception e) {
// Ignora exceções

} finally {
try {
if (fd != null)
fd.close();
} catch (IOException e) {
// Ignora exceções
}
}


Observação1: as classes usadas estão no pacote java.io:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;


Observação2: a variável filename é do tipo String.


**

Fica aqui a dica de três APIs interessantes.

[]'s
Cacilhas, La Batalema

quarta-feira, 11 de março de 2009

Quem vai pra Vala?

live.gnome.org Dessa vez o pessoal do Gnome acertou a mão. Estou falando da linguagem de programação Vala.

Até hoje, quem queria programar em C# era obrigado a usar ou um sistema operacional problemático, ou uma ferramenta monstruosamente pesada e ineficiente.

Não mais.

O projeto Gnome lançou há algum tempo a linguagem Vala, fortemente baseada na sintaxe do C#, mas voltada para aplicações Gnome. Quem manja de C# ou maja de Java e já viu C# não terá dificuldade em lidar com Vala.

Instalação


Segundo a página do projeto, Vala foi feito para plataforma Gnome. Surgiu aí meu primeiro problema: uso Slackware e o Volkerding decidiu que Slackware não terá mais suporte a Gnome! Em sua total substituição, há o Xfce.

Simplesmente não há um pacote oficial de Gnome para Slackware – e os não-oficiais que já experimentei simplesmente detonaram o sistema todo.

Ainda mais: e quem usa outros SOs? Se não tiver Gnome já era?

Qual não foi minha agradável surpresa quando descobri que Vala compilou e instalou sem problemas no Slackware 12.2?! Sua dependência verdadeira é GTK+ 2.x, que você encontra em praticamente qualquer distribuição GNU/Linux ou BSD.

E Windows? Também tem!

Usando


Um «Olá Mundo» em Vala é bastante simples (tanto quanto Java, pelo menos):
using GLib;

public class HelloWorld : Object {
public static int main(string[] args) {
stdout.printf("Olá Mundo!\n");
return 0;
}
}


Ao contrário do .NET, não há código escondido do programador. Por exemplo:
using GLib;

public class HelloWorld : Object {

private Gtk.Window window;


public HelloWorld() {
window = new Gtk.Window(Gtk.WindowType.TOPLEVEL);
window.set_default_size(300, 200);
window.destroy += Gtk.main_quit;
window.add(new Gtk.Label("Olá Mundo!"));
}


public void show() {
window.show_all();
Gtk.main();
}


public static int main (string[] args) {
Gtk.init(ref args);
var sample = new HelloWorld();
sample.show();

return 0;
}
}


Antes que alguém reclame, peço desculpas pelos códigos mal orientados a objetos, mas não quis ter muito o que explicar.
[update]Ajeitei pra ninguém ficar me chateando.[/update]

Maturidade


Estranhamente a linguagem já está bastante madura na 0.5.7. Não encontrei quebras inusitadas nem erros bizarros.

[update 2009-04-01]
Encontrei uma quebra inusitada: Vala não lida bem com closures e escopo dinâmico. Ela se perde um pouco gerando alguns erros inesperados.

Outro erro inconveniente está na API com C: o bind de método destruidor não suporta parâmetros, o que pode ocorrer em alguns casos da GLib – lembre-se do que não há métodos destruidores reais em C, mas sim funções de desalocação.
[/update]


A única coisa que tenho a reclamar muito é a documentação precária, bem longe das documentações de API bem organizadas da SUN Microsystems e da Microsoft.

IDE


Por enquanto há uma IDE chamada Val(a)IDE – só que essa já desarmou na minha cara algumas vezes – e a promessa de uma extensão para o Eclipse – que ainda não apareceu na página da própria extensão.

Segundo a página official, há também extensões para MonoDevelop (Deus me livre!) e para GEdit.

**

É isso aí! Quando eu ganhar um pouco mais de intimidade com a linguagem, escrevo mais alguma coisa. Por enquanto foi só divulgação. Um tutorial meia-boca pode ser encontrado aqui.

[]'s
Cacilhas, La Batalema

quarta-feira, 4 de março de 2009

Calculadora científica com o Vim

Desta vez vou reblogar

O voyeg3r publicou um artigo curtinho e muito legal sobre como criar uma calculadora científica no Vim usando Python.

O artigo pode ser encontrado no vivaotux.

Boa leitura!

[]'s
Cacilhas, La Batalema