Ajude a Wikipédia
Ajude a sustentar a Wikipédia e outros projetos, sem colocar a mão no bolso, e concorra a um Eee PC!
…e também a pen drives, card drives, camisetas geeks, livros e mais! O BR-Linux e o Efetividade lançaram uma campanha para ajudar a Wikimedia Foundation e outros mantenedores de projetos que usamos no dia-a-dia on-line. Se você puder doar diretamente, ou contribuir de outra forma, são sempre melhores opções. Mas se não puder, veja as regras da promoção e participe - quanto mais divulgação, maior será a doação do BR-Linux e do Efetividade, e você ainda concorre a diversos brindes!
Add comment 25/06/2008
Outro Blog
Faz algum tempo já, mas só para informar:
Eu e o Diogo criamos um blog para mostrar o pouco que nós (não) sabemos sobre Haskell e programação funcional.
Então conforme nós formos aprendendo sobre a assunto postaremos por lá.
Não deixem de conferir…
Add comment 30/05/2008
Funções
Neste artigo vou falar um pouco mais sobre funções. Mais precisamente sobre como passar um número variável de parâmetros para elas.
Existem basicamente 3 (três) formas de se fazer isso:
1 - Passagem segura quanto ao tipo
Nesse tipo, a parte dos parâmetros com número variável é passada como um array. Sendo assim, apenas um tipo de parâmetro pode ser passado, mas em qualquer quantidade.
Considere o exemplo:
void func(int[] p...)
{
foreach(i, v; p)
Stdout.formatln("p[{}] = {}", i, v);
}
Essa função pode ser usada como:
func()
func(10);
func(10, 15);
2 - Passagem estilo D
O porém de se usar a forma anterior é que apenas um tipo de argumento pode ser usado, e nem sempre isso é o desejado. Por isso existe um tipo, semalhante ao estilo C de se passar um número aleatório de parâmetros.
Considere o exemplo:
void func(...)
{
foreach(i, arg; _arguments)
{
if(arg == typeid(int))
Stdout.formatln("O argumento {} é um {} de valor {}", i, arg, *cast(int*)_argptr);
else if(arg == typeid(float))
Stdout.formatln("O argumento {} é um {} de valor {}", i, arg, *cast(float*)_argptr);
_argptr += arg.tsize;
}
}
Explanações
Quando é encontrado um “…” como argumento, você ganha duas variáveis ocultas: _arguments, um array de TypeInfo, e _argptr, um ponteiro void* para o primeiro argumento.´
Uma intância de TypeInfo é retornada pela expressão typeid, usada para RTTI (Run Time Type Information).
O método “tsize()” da classe TypeInfo retorna o tamanho do tipo.
Então basta ir tratando para cada tipo que você deseja que seja válido ou inválido:
assert(arg == typeid(char), "Tipo inválido");
Lembrando que um assert não termina o programa, simplesmente dispara um AssertError em Phobos ou um AssertException em Tango.
Só para frisar, se você estiver em um extern(C), você não ganha o _arguments.
3 - Tuplas
Esse tipo de passagem eu comecei a usar recentemente e, pelo menos para mim, já se tornou o melhor.
Uma tupla é um conjunto de coisas. Essas coisas podem ser tipos ou expressões, sendo que uma mesma tupla pode ter tipos e expressões, expressões de diferentes tipos, etc.
Esse tipo pode ser entendido como uma combinação dos dois anteriores, já que tuplas podem ser controladas como arrays, mas podem conter qualquer tipo em seu interior.
O único porém das tuplas é que seu tamanho deve estar disponível em tempo de compilação.
Para criar uma tupla, usa-se um template:
void func(P...)(P p)
{
foreach(i, v; p)
Stdout.formatln("p[{}] é um {} de valor {}", i, typeof(v).stringof, v);
}
Lembrando que void func(P…)(P p) é o mesmo que:
template func(P...)
{
void func(P p)...
}
Lembrando que typeof retorna o tipo de uma expressão e a propriedade “.stringof” converte qualquer expressão para uma string. E quando eu digo expressão, dessa vez é a expressão mesmo. Por exemplo: (5 + 1).stringof não rende a string “6″, mas sim “5 + 1″.
Por hoje é só. Logo entrarei em mais detalhes sobre Tuplas (e templates no geral).
blogblogs tags:linguagem, programacao, d
Add comment 15/04/2008
Lazy Evaluation - Parte II
No último post eu falei um pouco sobre as vantagens de se usar a a palavra lazy na passagem de parâmetros.
Então alguém pode pensar: “Legal, vou usar isso sempre”.
Mas não é bem assim que funciona.
Esse tipo de parâmetro tem a vantagem de ser avaliado apenas quando for usado, mas tem a desvantagem de ser avaliado sempre que for usado.
Confuso? Considere este exemplo:
/**
* testLazy.d - Exemplo de uso de parâmetros lazy.
*
* Author: Christian Hartung < hartung [at] live.com >
* Copyright: Domínio Público
*/
module testLazy;import tango.io.Stdout;
import tango.text.convert.Format;
const nrTests = 10;
void testLazy(lazy char[] str, int times)
{
for(int i = 0; i < times; i++)
Stdout(str())
}
void test(char[] str, int times)
{
for(int i = 0; i < times; i++)
Stdout(str)
}
void makeTests(alias Test)()
{
int j;
for(int i = 0; i < nrTests; i++)
{
Test(Format("{:d2} ", j++, 5), 10);
Stdout.newline()
}
Stdout.formatln("j = {}", j)
}
void main()
{
Stdout("Testando com lazy").newline
makeTests!(testLazy)();
Stdout.newline();
Stdout("Testando sem lazy").newline;
makeTests!(test)()
}
Neste exemplo, seria esperado que j = 10 ao final, mas usando lazy, j = 100.
Isso ocorre porque a cada vez que str é usado dentro de testLazy, todo o Format("{:d2} ", j++, 5) é avaliado, e o j++ é executado.
Já na função test str é avaliado apenas quando ela é chamada, ou seja, o j++ é avaliado apenas uma vez a cada chamada.
Ou seja, se você for usar seu parâmetro várias vezes dentro de sua função, o desempenho ganho com o uso de lazy pode ser perdido.
Outro problema que pode ocorrer:
int ops(bool b, lazy int i)
{
if(b)
return i();
return 0;
}
Se você chamar essa função como:
i = 1;
test(false, i++);Stdout.formatln("Sem lazy, i = {}", i);
Você vai perceber que o i não foi incrementado! Afinal, o segundo parâmetro de test não foi avaliado nenhuma vez.
Ou seja, apesar do aumento no desempenho que o uso de parâmtros lazy pode proporcionar, eles devem ser usados com cuidado.
blogblogs tags:linguagem, programacao, d
1 comment 05/04/2008
Lazy Evaluation
Agora, voltando a falar um pouco sobre funções, um conceito que pode ser muito útil é chamado Lazy Evaluation (Avaliação preguiçosa, ou algo do tipo).
Veja o exemplo dessa função:
string call(bool b, string s)
{
if(b)
return s;
else
return "";
}
Como podem ver, essa função (inútil, mas é apenas para demonstrar) retorna seu segundo argumento (s) se seu primeiro argumento (b) for verdadeiro.
Um problema com isso é que seu segundo argumento é sempre avaliado. Imaginando que ele seja uma função relativamente complexa, como a função “convert”, da classe Layout (função parecida com string.Format do C# ou String.format do Java), isso seria um desperdício de processamento) em casos como:
call(false, Format("{}", i));
(Format é uma “instância global” de Layout para char’s, definida em tango.text.convert.Format
Uma solução para isso seria passar um ponteiro para uma função ou um delegate (ponteiro para um membro, ou uma função interna) que faz a formatação:
call(false, { return Format("{}", i); });
Com isso, seria necessário trocar return s; em call por return s();.
Claro que é meio incomode ter que usar a sintaxe para delegates literais sempre que se quiser esse tipo de otimização, por isso foi criado o conceito de argumento preguiçoso (lazy), que basicamente é convertido para um delegate. Veja a função:
string lazyCall(bool b, lazy string s)
{
if(b)
return s();
else
return "";
}
Obs.: string é um alias que eu criei para um array de char’s ou invariant(char)’s, dependendo da versão da linguagem ou biblioteca sendo usada. Ele é definido como:
static if(!is(string))
{
static if(is(typeof(object.Object.toString) R == return))
alias R string;
}
Esse trecho verifica se já não existe um tipo string já definido (lembrando que ele foi adicionado ao módulo “object” para Phobos v2). Se não existir, ele pega o tipo que o método toString (método existente em Phobos e adicionado à Tango na versão 0.99.4 Frank - antes disso era toUtf8 da classe Object (classe esta existente em Phobos e em Tango no módulo object) em R e cria um alias para esse tipo como string. Uma observação: não vá confundir o typeof em D e em C#. Em C#, você usaria typeof(tipo) para retornar uma instância de System.Type para o tipo (ou algo do tipo) passado. Em D, você usa typeof(variável) para retornar o tipo da variável.
static if é uma forma de compilação condicional da linguagem. A condição dessa instrução é avaliada em tempo de compilação, e não é criado um novo escopo para seu bloco de instruções.
Esta forma de is é para verificar, em tempo de compilação, a validade ou não de algum tipo. Mais informações sobre isso futuramente (assim espero!).
Para demonstrar a eficiência disso, criei este simples benchmark:
module Lazy; import tango.io.Stdout;
import tango.text.convert.Format;
import tango.time.StopWatch;const j = 10000000u; static if(!is(string))
{
static if(is(typeof(object.Object.toString) R == return))
alias R string;
}
string lazyCall(bool b, lazy string s)
{
if(b)
return s();
else
return "";
}
string call(bool b, string s)
{
if(b)
return s;
else
return "";
}
private void benchmarkImpl(alias fn)(bool b)
{
StopWatch e;
Stdout.formatln("Executando {} vezes com b = {}", j, b);
e.start();
for(uint i = 0; i < j; i++)
fn(b, Format("{}", i));
Stdout.formatln("Tempo de execução: {}", e.stop()).newline;
}
void benchmark(alias fn)()
{
benchmarkImpl!(fn)(true);
benchmarkImpl!(fn)(false);
}
void main()
{
Stdout("lazyCall").newline;
benchmark!(lazyCall)();
Stdout("-----------------------").newline; Stdout("call").newline;
benchmark!(call)();
}
Coloque isso em um arquivo chamado Lazy.d e compile (tomara que compile).
Acho que a única novidade nesse código é o private void benchmarkImpl(alias fn)(bool b).
Então, vejamos o que é isso:
private, assim como para classes, torna a função benchmarkImpl visível apenas para o módulo Lazy (lembrando que em OOP em D, campos/métodos privados são visíveis para todo o módulo, não apenas para a classe, semelhantemente ao Delphi - mas não tente colocar strict private para mudar isso).
Fora isso, sobrou apenas a parte legal da declaração:
void benchmarkImpl(alias fn)(bool b).
Isso é equivalente a declarar um template da seguinte forma:
template benchmarkImpl(alias fn)
{
void benchmarkImpl(bool b) { ... }
}
O alias na declaração do template, neste caso, aceita símbolos globais no geral (no caso, uma função).
Usando Phobos (a biblioteca padrão), o exemplo ficaria mais ou menos assim:
module Lazy;import std.perf;
import std.stdio;
import std.string;
const j = 10000000u;
static if(!is(string))
{
static if(is(typeof(object.Object.toString) R == return))
alias R string;
}
string lazyCall(bool b, lazy string s)
{
if(b)
return s();
else
return "";
}
string call(bool b, string s)
{
if(b)
return s;
else
return "";
}
private void benchmarkImpl(alias fn)(bool b)
{
auto e = new PerformanceCounter();
writefln("Executando %s vezes com b = %s", j, b);
e.start();
for(uint i = 0; i < j; i++)
fn(b, format("%s", i));
e.stop;
writefln("Tempo de execução: %s", e.milliseconds / 1000.0);
}
void benchmark(alias fn)(){
benchmarkImpl!(fn)(true);
benchmarkImpl!(fn)(false);
}
void main(){
writefln("lazyCall");
benchmark!(lazyCall)();
writefln("-----------------------"); writefln("call");
benchmark!(call)();
}
blogblogs tags:linguagem, programacao, d
Add comment 19/02/2008
DSSS
O D Shared Software System é um “sistema de compartilhamento de software” criado para facilitar a utilização de bibliotecas de terceiros, e (o que eu uso com mais frequencia) como um sistema para automatizar a compilação de softwares.
Suponha que você esteja escrevendo uma biblioteca. Esta provavelmente terá vários módulos. Utilizando simplemente o compilador, você teria que especificar todos os módulos. Por exemplo:
dmd -c Soma.d Mul.d Sub.d Div.d
(-c para não linkar, apenas compilar e não linkar - não gerando o executável)
Quando seu aplicativo vai crescendo, começa a ficar incomodo listar todos os arquivos (ou criar um script, como um makefile e especificá-los). É aí que entra uma ferramenta como o DSSS.
Continuando o exemplo anterior, teríamos os módulos:
module matematica.Soma;
int soma(int a, int b)
{
return a + b;
}
//--------------------------------module matematica.Sub;
int sub(int a, int b)
{
return a - b;
}
//--------------------------------module matematica.Mul;
int mul(int a, int b)
{
return a * b;
}
//--------------------------------
module matematica.Div;
int div(int a, int b)
{
if(b == 0)
return a;
return a + b;
}
//--------------------------------
Para tornar essa biblioteca “usável” com o DSSS, você simplesmente deve criar um script chamado “dsss.conf” na raíz de seu aplicativo:
- dsss.conf - matematica - - Soma.d - - Sub.d - - Mul.d - - Div.d
O script se assemelha à um arquivo .ini do Windows:
name=matematica[matematica]
type=library
target=matematica
Esse script criará um sistema chamado matematica (se ele for instalado via DSSS, terá esse nome), que terá uma biblioteca compilada com os arquivos dentro do pacote “matematica”, e que se chamará “matematica.lib” no Windows e “libmatematica.a” em sistemas POSIX.
No geral, não é necessário informar o tipo, mas eu prefiro, só por documentação.
Agora, basta entrar no diretório que contém esse script e digitar no console dsss build (claro que isso depois de configurar o PATH, como já é de costume). Se houver documentação das funções no formato DDOC, você pode usar dsss build –doc
Se desejar instalar essa biblioteca, para que possa ser usada por outros sistemas, basta usar dsss install.
Se desejar adicionar um binário qualquer à sua biblioteca (por exemplo, main.d no diretório raíz):
- dsss.conf - matematica - - Soma.d - - Sub.d - - Mul.d - - Div.d - main.d
Basta adiciná-lo ao script dsss.conf:
name=matematica[matematica]
type=library
target=matematica
[main.d]type=binary
target=testmatematica
Desta vez, além da biblioteca, também será gerado um executável (type=binary) chamado testmatematica(\.exe)?
Add comment 14/02/2008
DFL - Parte III - Posicionamento
Agora vamos aprender a posicionar elementos na tela.
Para isso, vamos construir uma simples tela de Login. Ela se parecerá com esta:
O fonte para isso:
/**
* login.d - Exemplo de Tela de Login usando DFL.
*
* Author: Christian Hartung < hartung [at] live.com >
* Copyright: Domínio Público
*/
module login;
import dfl.application : Application;
import dfl.base : ContentAlignment;
import dfl.button : Button;
import dfl.drawing : Point, Rect, Size;
import dfl.form : FormBorderStyle, FormStartPosition, Form;
import dfl.label : Label;
import dfl.messagebox : MsgBoxButtons, MsgBoxIcon, msgBox;
import dfl.textbox : TextBox;
class LoginForm : Form
{
this()
{
super();
init();
}
void init()
{
with(loginL = new Label())
{
parent = this;
text = "Login:";
size = Size(40, 20);
location = Point(10, 10);
textAlign = ContentAlignment.MIDDLE_CENTER;
}
with(loginTB = new TextBox())
{
parent = this;
bounds = Rect(50, 10, 150, 20);
}
with(senhaL = new Label())
{
parent = this;
text = "Senha:";
bounds = Rect(10, 40, 40, 20);
textAlign = ContentAlignment.MIDDLE_CENTER;
}
with(senhaTB = new TextBox())
{
parent = this;
bounds = Rect(50, 40, 150, 20);
passwordChar = '*';
}
with(okB = new Button())
{
parent = this;
text = "OK";
bounds = Rect(50, 65, 70, 25);
}
with(cancelarB = new Button())
{
parent = this;
text = "Cancelar";
bounds = Rect(130, 65, 70, 25);
}
this.text = "Login";
this.startPosition = FormStartPosition.CENTER_SCREEN;
this.formBorderStyle = FormBorderStyle.FIXED_DIALOG;
this.size = Size(215, 125);
}
private Label loginL, senhaL;
private TextBox loginTB, senhaTB;
private Button okB, cancelarB;
}
void main(char[][] args)
{
try
{
Application.run(new LoginForm());
}
catch(Exception e)
{
msgBox(e.toString(), "Erro", MsgBoxButtons.OK,
MsgBoxIcon.ERROR);
}
}
Explicações
Primeiramente, como uma boa prática (que eu raramente sigo, só para frisar), documentação do arquivo, iniciando-o com um comentário sobre o que ele faz. “Author:” e “Coryright:” estão assim pois é dessa forma que o DDoc interpreta.
Agora os imports. Essa forma de importar (com o ‘:’), indica que estou importando apenas esses símbolos dos arquivos. Ou seja, se há um ‘:’ após o nome do módulo sendo importado, só será possível utilizar os símbolos (classes, funções, enums, …) que são especificados.
No método main, tudo o que é feito é executar a aplicação, passando para ela um formulário principal, no caso uma intância de LoginForm. Se algum erro não tratado pela aplicação ocorrer, ele simplesmente será exibido em uma caixa de mensagem, com o título “Erro”, um ícone de erro (normalmente um “X”).
No geral, seu método main terá sempre essa aparência, a não ser que você queira, por exemplo, processar os argumentos de linha de comando.
A classe LoginForm
Como D é uma linguagem orientada a objetos (e ninguém mecere criar o formulário inteiro no método main, como foi feito até a última parte do tutorial, é melhor criar uma classe para seu formulário.
Não vou fazer um tutorial completo sobre orientação a objetos em D agora. Isso vai sendo feito aos poucos no decorrer dos tutoriais (ou o que seria melhor, criar uma série sobre Orientação a Objetos).
O que você precisa saber agora é que:
- D possui apenas herança simples, complementada com o uso de Interfaces e Mixins (logo vocês saberão para que isso serve);
- O construtor da classe é um método chamado
this(), que pode ser sobrecarregado; - Para se referir à classe pai, usa-se
super; - Tudo na classe é público, a não ser que seja específicado o contrário (no caso, o construtor e o método
init()são públicos, ou seja, acessíveis em qualquer lugar do programa). - Os membros privados (no caso, os controles do formulário) são acessíveis por todo o módulo (e não apenas pela classe a que pertencem).
Outra coisa importante, e muito útil (ao menos em linguagens orientadas a objetos) é a instrução with. Ela permite que você omita o nome de sua variável (objeto ou estrutura) para acessar seus membros. Basicamente, quando um símbolo é encontrado dentro do bloco with, primeiramente ele é buscado na variável específicada, e depois em outros escopos. No caso, os atributos parent, text, … referem aos membros dos controles.
Posicionando controles
Para se posicionar um controle, existem três propriedades que podem ser usadas:
size= propriedade do tipoSize, que é uma estrutura definida emdfl.drawing. É passado um comprimento e uma altura;location= propriedade do tipoPoint, que é outra estrutura definida emdfl.drawing. São passadas as coordenadas x e y;bounds= propriedade do tipoRect, que é outra estrutura definida emdfl.drawing. São passados um comprimento, uma altura, a coordenada x e a coordenada y.
E, só para frisar, também existe o método setBounds(), que também recebe um comprimento, uma altura, a coordenada x e a coordenada y. Há também uma versão desse método que recebe flags do tipo BoundsSpecified, uma enumeração definida no módulo dfl.control. Seus valores são: NONE, X, Y, LOCATION, WIDTH, HEIGHT, SIZE, ALL. Ela indica quais dos outros parâmetros serão usados para posicionar o controle. Por exemplo:
setBounds(10, 10, 40, 20, BoundsSpecified.ALL)= indica que o controle será posicionado nas coordenadas x=10, y=10 e terá 40×20 de tamanho;setBounds(10, 10, 40, 20, BoundsSpecified.X)= indica que o controle será posicionado na coordenadas x=10. Os outros pontos não será ajustados;setBounds(10, 10, 40, 20, BoundsSpecified.SIZE)= indica que o controle terá 40×20 no tamanho, mas sua posição não será alterada;setBounds(10, 10, 40, 20, cast(int)(BoundsSpecified.SIZE, BoundsSpecified.LOCATION))= o mesmo queBoundsSpecified.ALL.
Lembrando que para que o controle apareça, é necessário ajustar a propriedade parent seu “dono” (no caso, uma instância qualquer de LoginForm, por isso está sendo passado o this, que representa o objeto chamando o método).
Outras propriedades
Algumas outras propriedades que ajudam no posicionamento são:
textAlign- Propriedade do
Labeldo tipoContentAlignment, que indica o alinhamento do texto dentro do tamanho doLabel. É definida (emdfl.base) como:enum ContentAlignment: ubyte { TOP_LEFT, BOTTOM_CENTER, BOTTOM_LEFT, BOTTOM_RIGHT, MIDDLE_CENTER, MIDDLE_LEFT, MIDDLE_RIGHT, TOP_CENTER, TOP_RIGHT } startPosition- Propriedade do
Formdo tipoFormStartPosition, que indica a posição inicial do formulário na tela. É definida (emdfl.form) como:enum FormStartPosition: ubyte { CENTER_PARENT, CENTER_SCREEN, MANUAL, DEFAULT_BOUNDS, DEFAULT_LOCATION, }
Outra propriedade que foi usada: formBorderStyle, do formulário, que indica o estilo da borda. A propriedade é do tipo FormBorderStyle, que tem a seguinte definição:
enum FormBorderStyle: ubyte { NONE, /// Sem borda FIXED_3D,/// Borda fixa, com um efeito de relevoFIXED_SINGLE,/// Borda fixa comumFIXED_DIALOG,/// Borda fixa comum para diálogosSIZABLE,/// Borda redimensionávelFIXED_TOOLWINDOW,/// Borda fixa, sem ícone e apenas com botão de fecharSIZABLE_TOOLWINDOW/// Borda redimensionável,sem ícone e apenas com botão de fechar}
Uma última propriedade utilizada, que não tem ligação com posicionamento, foi passwordChar, do TextBox, que indica o caractere que será exibido quando se digitar algo na caixa. Se houver algum caractere nela (i.e. passwordChar != ”), também não será possível copiar o text da caixa.
Por hoje vou parando por aqui. Na próxima parte, vou mostrar como adicionar alguma funcionalidade aos botões “OK” e “Cancelar”… Até lá.
blogblogs tags:linguagem, programacao, d
Blogged with Flock
Tags: linguagem, programacao, d
Add comment 07/01/2008
DFL - Parte II - Adicionando Componentes
Hello again!!
Aproveitando a oportunidade, vamos aprender a adicionar um componente ao nosso formulário.
// hello.d - Hello World usando DFL
module hello;
import dfl.application;
import dfl.form;
import dfl.label;
void main(char[][] args)
{
auto frm = new Form();
frm.text = "Meu Programa";
auto texto = new Label();
texto.text = "Olá Mundo";
texto.parent = frm;
Application.run(frm);
}
A primeira coisa que você deve saber: se você não quiser ficar importando cada módulo que for usar, você pode simplesmente importar o módulo dfl.all, que importa a biblioteca toda.
Com relação ao último programa, apenas foi adicionado o um texto. Para isso, simplesmente adicione um componente Label. É importante notar que para efetivamente adicionar um componente, deve-se colocar seu dono na propriedade parent, como no exemplo, texto.parent = frm, que diz que o dono do componente texto é o componente frm.
Nota: talvez ocorra um erro na hora de compilar indicando algo do tipo uma string UTF8 inválida. Isso porque há um acento em “Olá”. Para corrigir isso, salve seu arquivo com a codificação UTF8 (com BOM).
Nota 2: Acostume-se a colocar a declaração do módulo em seus arquivos, apesar de ela não ser obrigatória.
blogblogs tags:linguagem, programacao, d
Add comment 30/12/2007
DFL - Parte I
Desculpem a ausência, mas estive meio ocupado por uns tempos.
Mas agora que estou de férias (ao menos da faculdade) , vou tentar postar mais freqüêntemente.
Para começar, vou tentar fazer um pequeno curso sobre DFL (D Forms Library).
Descrição
Como eu já devo ter dito, DFL é uma biblioteca gráfica para a linguagem D, atualmente baseada na Win32 API, e já sendo portada para Gtk - sim, por enquanto (in)felizmente você só poderá usá-la no Windows.
Sendo baseada nessas APIs, ela lida com interfaces “nativas”, apenas mapeando as funções dessas bibliotecas para algo mais amigável para se trabalhar. Também ela se assemelha ao Windows Forms do .NET.
Instalação
Primeiramente, você precisa ter o DMD (Digital Mars D compiler) versão 1.xxx. Baixe-o aqui. Você também pode baixá-lo já configurado com a biblioteca Tango (eu prefiro assim, mas você é quem sabe que biblioteca usar. Vou tentar postar os exemplos usando ambas as bibliotecas quando for necessário) aqui. Também será necessário o DMC (Digital Mars C compiler), que é usado como backend para o DMD.
Extraia os arquivos em qualquer lugar. Isso criará os diretórios dm e dmd (se baixar a versão que vem com Tango, crie um diretório dmd e extraia seus arquivos lá). Agora basta adicionar ao PATH (Win + Pause Break -> Avançado -> Variáveis de Ambiente no Windows XP ou Vista, ou edite Autoexec.bat nos outros Windows) os diretórios dmd\bin e dm\bin. Certifique-se de adicionar dm\bin antes de qualquer outro diretório que contenha um link.exe, ou você poderá ter problemas para compilar (linkar, na verdade).
Agora, baixe DFL aqui. Extraia dentro de seu diretório dmd. Isso criará um diretório dfl dentro de import. Aí estão os fontes da biblioteca se você quiser dar uma olhada.
Mais uma coisa: copie os arquivos de dm\lib para dmd\lib. Isso evitará problemas futuros.
Seu Segundo Programa
Sim, afinal, já postei como criar uma caixa de texto algum tempo atras.
// teste.d - Teste da biblioteca DFL
module teste;
import dfl.application;
import dfl.form;
void main(char[][] args)
{
auto frm = new Form();
frm.text = "Meu Programa";
Application.run(frm);
}
PS.: Sim, tomei como base o Curso de wxWidgets do Just (espero que não se importe de eu eventualmente usar alguns exemplos de lá, ao menos agora no início).
Compilando
Para compilar, basta usar o utilitário dfl que está em dmd\bin:
dfl -gui teste.d
Ops: se você está usando a última versão de Tango (0.94 - Frank), provavelmente terá alguns erros de compilação. Isso porque (finalmente) seus criadores substituíram os toUtf8() de todas as classes para toString(). Então, por favor, substitua esses erros nos arquivos em dmd\import\dfl\?.
Pronto, agora você deve ter um arquivo teste.exe.
blogblogs tags:linguagem, programacao, d
Add comment 29/12/2007


