Desenvolvimento
   Rápido de
 Aplicações com
  Tcl e XOTcl
Porque usar scripts?
●
    Interatividade: não há o ciclo “edita-compila-
    testa”.
●
    Menos linhas de código (alto-nível).
●
    Melhor representação dos dados (no Tcl, por
    exemplo, tudo é string).
●
    Portabilidade. (Linux (e outros unices),
    Windows, Mac, mobile, embedded, ...)
O que podemos fazer com Tcl?
●
    MITO: linguagens de script são muito lentas,
    não devem ser usadas em aplicações velozes
    (processamento de vídeo, por exemplo)
●
    REALIDADE: só uma pequena fração do
    código precisa ter velocidade extrema; scripts
    nos fornecem mais controle, flexibilidade e
    menos linhas de código.
Starkits
●
    Scripts e extensões encapsulados em um único
    arquivo (.kit), portável (Linux/Windows/Mac)
●
    Executável separado para cada plataforma:
    tclkit, tclkit.exe
●
    Diretório virtual. Pode conter scripts, bibliotecas
    (multiplas versões, uma para cada OS),
    documentação. Implementado no topo do
    banco de dados Metakit.
Manipulando kits
●
    Utilitário sdx
    ●   sdx qwrap programa.tcl
        –   Gera um kit a partir do script fornecido
    ●   sdx unwrap programa.kit
        –   Expande o kit como o diretório programa.vfs
    ●   sdx wrap programa.kit
        –   Reempacota o kit usando o diretório programa.vfs
        –   Opcionalmente, podemos usar -runtime tclkit para
            produzir um starpack (tudo em um só executável).
Bibliotheca
Bibliotheca (2)
●
    Cada livro é representado por uma imagem
    (capa) de tamanho reduzido.
●
    Formatos dos arquivos (livros): pdf, djvu,
    chm, ps,...(outros podem ser suportados
    facilmente)
●
    Comandos para incluir novos livros,
    reorganizar as “estantes”, criar ícones para
    um livro, ou até para transferir o conteúdo
    (ssh) a partir de um servidor.
Bibliotheca (3)
●
    Informações sobre livros armazenados numa
    lista:

    <arquivo_do_livro> <ícone> <estante>

    ●   Todos os livros localizados em um diretório
        único, configurável.
    ●   Ícones de tamanho até 96x128 pixels,
        variável.
    ●   Cada “estante virtual” agrupa livros de
        assunto similar.
Bibliotheca (4)
Bibliotheca (5)
proc showDoc {fn} {
global P
after cancel setupButMotion
switch [file extension $fn] {
   ".Chm" -
   ".chm" {
      set P(chan) [open "|xchm "$fn"" r+] }
   ".Pdf" -
   ".pdf" -
   ".PDF" {
      set P(chan) [open "|acroread "$fn"" r+] }
   ".djvu" { set P(chan) 
         [open "|djview "$fn"" r+] }
   default { set P(chan) [open "|gv "$fn"" r+] }
}
fileevent $P(chan) readable 
      [list execHndl $P(chan)]
}
Critcl
●
    Permite criar novos comandos (extensões para
    o Tcl) em C, em scripts.
    package provide fork 1.0
    critcl::ccode {
       #include <unistd.h>
    }
    critcl::cproc fork {} int {
       return fork();
    }

●
    Compilado com: critcl -pkg fork
●
    Extensão produzida pode ser incluida na
    aplicação normalmente, com:
Aplicação com dual vídeo
Libavformat/avcodec + SDL
       interfaceados com Tcl
●
    libavformat/avcodec (ffmpeg)
    ●
        Decodifica vídeo/áudio
    ●
        Redimensiona os quadros (video frames)
●
    SDL
    ●
        Preenche os buffers de vídeo na tela, usando MMX
        e outras tecnologias para obter maior desempenho
●
    Tcl
    ●
        Aplicação principal: controla todo o contexto
Dual vídeo extension
package provide embvideo 1.0
critcl::cheaders -g -I. -DLINUX 
   -I/usr/local/include/ffmpeg/ -I/usr/local/include/

critcl::clibraries -L/usr/lib -L/usr/local/lib 
   -lavformat -lavcodec -lavutil -lSDL -lSDL_image -lz

critcl::ccode {
   #include "embvideo.c"
}
::critcl::cproc vidinit { Tcl_Interp* ip
      int wid int dual } ok {
   ...
   return TCL_OK;
}
. . .
. . .
Dual vídeo extension (2)
●   Usa 3 buffers (shared memory) para enviar video
    frames, comandos e status entre os processos
    de vídeo/audio, sincronizando a comunicação
    por meio de signals.
        mmfd = open("/dev/zero",O_RDWR);
        mmpixels = mmap(0,sfrw*sfrh*3, PROT_READ|PROT_WRITE,
        MAP_SHARED, mmfd, 0);
        close(mmfd);

●
    Comandos ofertados ao script tcl:
    ●   vidsetmovie <audio/video_filename>
        vidcmd <large | small>
        vidinit <window id> <flags>
        vidcheckend, vidwait, vidquit
Protocolo do libavformat
URLProtocol decrypt_protocol = {
    "decrypt",
    decrypt_open,
    decrypt_read,
    NULL /*decrypt_write*/,
    decrypt_seek,
    decrypt_close,
};


             decrypt:arquivo_video_audio

  Registrando o novo protocolo em libavformat:
        register_protocol(&decrypt_protocol);
XOTcl (exotickle)
●
    Sistema de objetos poderoso, baseado no
    CLOS (Common Lisp Object System)
●
    Adiciona dois novos comandos apenas: Object
    e Class.
●
    Introspecção completa em todos os aspectos
    dos objetos através do comando standard já
    presente no tcl, info.
●
    Suporte a muitas abstrações como filtros,
    mixins, slots, nested classes, method
XOTcl (2)
Exemplo: configurador.xotcl
●
    Definindo (ou adicionando) uma ou mais
    opções:
    ●   config state {width 800 height 600
          background “cadet blue”}
●
    Apagando todas as opções armazenadas:
    ●   config state -clear yes
●
    Obtendo todas as opções existentes:
    ●   config state
●
    Outros comandos: config   load, config save
configurador.xotcl
Object config
config proc state {{-clear 0} {newstate ""}} {
   if {$newstate != ""} {
      foreach {v contents} $newstate {
         my set $v $contents
      }
   }
   set r {}
   foreach v [my info vars] {
      lappend r $v [my set $v]
   }
   if $clear {
      foreach v [my info vars] {
         my unset $v
      }
   }                            my
                                 my       [self]
                                           [self]
   return $r
}
configurador.xotcl (3)
config proc save {filename} {
  set f [open $filename w]
  puts $f [my state]
  close $f
}

config proc load {filename} {
  set f [open $filename r]
  my state [read $f]
  close $f
}
Peculiaridades do XOTcl
●
    XOTcl tem caraterísticas diferentes do
    tradicional (C++/Java):
    ●
        Sistema de classes dinâmico. Tudo pode ser mudado a
        qualquer instante.
    ●
        É voltado aos objetos e não às classes, ou seja, cada
        objetos tem vida independente, podendo ter suas
        próprias “procs”, variáveis específicas do objeto, etc.
    ●
        É completamente reflexiva (um programa pode
        observar seu próprio comportamento e modificá-lo, se
        desejado).
XOTclIDE


Component browser




                Object Browser
Classes e Objetos
●
    Uma classe generaliza operações e variáveis
    dos objetos (instâncias).
      Class   Curso
      Curso   instproc init args {
         my   set pre-requisitos ""
      }
      Curso   instproc sethorario hr {
         my   set horario $hr
      }

      Curso historia -sethorario 10:30
Precedência do next
Class Terrestre
Class Maritimo
Terrestre instproc desc args {return "-terrestre-
[next]"}
Maritimo instproc desc args {return "-maritimo-[next]"}

Class Anfibio -superclass {Terrestre Maritimo}
Anfibio   instproc desc args {return "-anfibio-[next]"}

Terrestre automovel
Maritimo lancha
lancha proc desc args {return "-lancha-[next]"}

Anfibio hovercraft
   -terrestre-
hovercraft proc desc args {return "-hovercraft-[next]"}
   -lancha—maritimo-
   -hovercraft--anfibio--terrestre--maritimo-
Nested objects
●   historia contains {Object idade_media}
●   Class Point -parameter {{x 100} {y 300}}
    Class Rectangle -parameter {color}
    Rectangle r0 -color pink -contains {
       Rectangle r1 -color red -contains {
          Point x1 -x 1 -y 2
          Point x2 -x 1 -y 2
       }
       Rectangle r2 -color green -contains {
          Point x1
          Point x2
       }
    }

                      ::historia::idade_media

                      historia idade_media
Filtros
Object instproc exempFiltro {args} {
   puts "self        = [self]"
   puts "calledproc = [self calledproc]"
   puts "args = $args"
   puts ---------------------------
   next
}

Class TesteClass
TesteClass filter exempFiltro
TesteClass umObjeto

                        className instproc FilterName args {
                           pre-part
                           next
                           post-part
                         }
Filtros (2)
●
    Filtros “por objeto” e “por classe”
      Class Painel
      Painel p1
      Painel p2

      Painel instproc observaFiltro args {
         puts "observaFiltro para objeto: [self]"
         set r [next]
         puts "observaFiltro (obj=[self]) retornou: $r"
      }

      Painel instfilter observaFiltro
Mixins
Class   Agent
Agent   instproc move {x y} {
    #   do the movement
}
Class   InteractiveAgent -superclass Agent

Class MovementLog
MovementLog instproc move {x y} {
    # movement logging
    next
}
Class MovementTest
MovementTest instproc move {x y} {
    # movement testing
    next
}

InteractiveAgent i1; InteractiveAgent i2
i1 mixin MovementLog
i2 mixin MovementTest MovementLog
Slots
●
    System slots: superclass,      class, mixin, instmixin,
    filter, instfilter.

●
    Attribute slots.
      Class Person -slots {
         Attribute name
         Attribute salary -default 0
         Attribute projects -default {}
            -multivalued true
      }                                 Acessa o slot meta-objeto
      Person slot name

      Person rildo
      rildo name “Rildo Pragana”
      rildo name
A função primitiva self
self – retorna o nome do objeto em execução
self class – retorna a classe que define a instproc corrente
self proc – retorna a proc ou instproc em execução
self callingclass – retorna a classe que chamou
     este método
self callingobject – objeto que chamou este método
self callingproc – a proc (ou método) que chamou
     o método corrente
self calledclass – a classe que contem essa
     proc (mixins, filters)
self calledproc – nome do método da proc alvo
     (só em filtros).
self isnextcall – retorna 1 se chamado por “next”
self next – retorna o path do próximo “next”
self filterreg – em um filtro: retorna o nome da classe/objeto
     onde foi registrado na forma 'obj filter nomeDoFiltro'
     ou 'classe instfilter nomeDoFiltro'
self callinglevel – nível da chamada
self activelevel – nível da pilha onde a proc foi chamada
Links interessantes
●
    http://www.pragana.net - Adventures in Linux
       Programming
●
    http://wiki.tcl.tk - Tcler's wiki (farta
       documentação!)
●
    http://www.tcl.tk - Tcl developer exchange
●
    http://media.wu-wien.ac.at - XOTcl homepage
●
    http://www.xdobry.de/xotclIDE/ - XOTclIDE
       homepage
●
    http://openacs.org - OpenACS (toolkit para
       aplicações web)
●
Perguntas




                ?
?
         ?

Palestra2009

  • 1.
    Desenvolvimento Rápido de Aplicações com Tcl e XOTcl
  • 2.
    Porque usar scripts? ● Interatividade: não há o ciclo “edita-compila- testa”. ● Menos linhas de código (alto-nível). ● Melhor representação dos dados (no Tcl, por exemplo, tudo é string). ● Portabilidade. (Linux (e outros unices), Windows, Mac, mobile, embedded, ...)
  • 3.
    O que podemosfazer com Tcl? ● MITO: linguagens de script são muito lentas, não devem ser usadas em aplicações velozes (processamento de vídeo, por exemplo) ● REALIDADE: só uma pequena fração do código precisa ter velocidade extrema; scripts nos fornecem mais controle, flexibilidade e menos linhas de código.
  • 4.
    Starkits ● Scripts e extensões encapsulados em um único arquivo (.kit), portável (Linux/Windows/Mac) ● Executável separado para cada plataforma: tclkit, tclkit.exe ● Diretório virtual. Pode conter scripts, bibliotecas (multiplas versões, uma para cada OS), documentação. Implementado no topo do banco de dados Metakit.
  • 5.
    Manipulando kits ● Utilitário sdx ● sdx qwrap programa.tcl – Gera um kit a partir do script fornecido ● sdx unwrap programa.kit – Expande o kit como o diretório programa.vfs ● sdx wrap programa.kit – Reempacota o kit usando o diretório programa.vfs – Opcionalmente, podemos usar -runtime tclkit para produzir um starpack (tudo em um só executável).
  • 6.
  • 7.
    Bibliotheca (2) ● Cada livro é representado por uma imagem (capa) de tamanho reduzido. ● Formatos dos arquivos (livros): pdf, djvu, chm, ps,...(outros podem ser suportados facilmente) ● Comandos para incluir novos livros, reorganizar as “estantes”, criar ícones para um livro, ou até para transferir o conteúdo (ssh) a partir de um servidor.
  • 8.
    Bibliotheca (3) ● Informações sobre livros armazenados numa lista: <arquivo_do_livro> <ícone> <estante> ● Todos os livros localizados em um diretório único, configurável. ● Ícones de tamanho até 96x128 pixels, variável. ● Cada “estante virtual” agrupa livros de assunto similar.
  • 9.
  • 10.
    Bibliotheca (5) proc showDoc{fn} { global P after cancel setupButMotion switch [file extension $fn] { ".Chm" - ".chm" { set P(chan) [open "|xchm "$fn"" r+] } ".Pdf" - ".pdf" - ".PDF" { set P(chan) [open "|acroread "$fn"" r+] } ".djvu" { set P(chan) [open "|djview "$fn"" r+] } default { set P(chan) [open "|gv "$fn"" r+] } } fileevent $P(chan) readable [list execHndl $P(chan)] }
  • 11.
    Critcl ● Permite criar novos comandos (extensões para o Tcl) em C, em scripts. package provide fork 1.0 critcl::ccode { #include <unistd.h> } critcl::cproc fork {} int { return fork(); } ● Compilado com: critcl -pkg fork ● Extensão produzida pode ser incluida na aplicação normalmente, com:
  • 12.
  • 13.
    Libavformat/avcodec + SDL interfaceados com Tcl ● libavformat/avcodec (ffmpeg) ● Decodifica vídeo/áudio ● Redimensiona os quadros (video frames) ● SDL ● Preenche os buffers de vídeo na tela, usando MMX e outras tecnologias para obter maior desempenho ● Tcl ● Aplicação principal: controla todo o contexto
  • 14.
    Dual vídeo extension packageprovide embvideo 1.0 critcl::cheaders -g -I. -DLINUX -I/usr/local/include/ffmpeg/ -I/usr/local/include/ critcl::clibraries -L/usr/lib -L/usr/local/lib -lavformat -lavcodec -lavutil -lSDL -lSDL_image -lz critcl::ccode { #include "embvideo.c" } ::critcl::cproc vidinit { Tcl_Interp* ip int wid int dual } ok { ... return TCL_OK; } . . . . . .
  • 15.
    Dual vídeo extension(2) ● Usa 3 buffers (shared memory) para enviar video frames, comandos e status entre os processos de vídeo/audio, sincronizando a comunicação por meio de signals. mmfd = open("/dev/zero",O_RDWR); mmpixels = mmap(0,sfrw*sfrh*3, PROT_READ|PROT_WRITE, MAP_SHARED, mmfd, 0); close(mmfd); ● Comandos ofertados ao script tcl: ● vidsetmovie <audio/video_filename> vidcmd <large | small> vidinit <window id> <flags> vidcheckend, vidwait, vidquit
  • 16.
    Protocolo do libavformat URLProtocoldecrypt_protocol = { "decrypt", decrypt_open, decrypt_read, NULL /*decrypt_write*/, decrypt_seek, decrypt_close, }; decrypt:arquivo_video_audio Registrando o novo protocolo em libavformat: register_protocol(&decrypt_protocol);
  • 17.
    XOTcl (exotickle) ● Sistema de objetos poderoso, baseado no CLOS (Common Lisp Object System) ● Adiciona dois novos comandos apenas: Object e Class. ● Introspecção completa em todos os aspectos dos objetos através do comando standard já presente no tcl, info. ● Suporte a muitas abstrações como filtros, mixins, slots, nested classes, method
  • 18.
  • 19.
    Exemplo: configurador.xotcl ● Definindo (ou adicionando) uma ou mais opções: ● config state {width 800 height 600 background “cadet blue”} ● Apagando todas as opções armazenadas: ● config state -clear yes ● Obtendo todas as opções existentes: ● config state ● Outros comandos: config load, config save
  • 20.
    configurador.xotcl Object config config procstate {{-clear 0} {newstate ""}} { if {$newstate != ""} { foreach {v contents} $newstate { my set $v $contents } } set r {} foreach v [my info vars] { lappend r $v [my set $v] } if $clear { foreach v [my info vars] { my unset $v } } my my [self] [self] return $r }
  • 21.
    configurador.xotcl (3) config procsave {filename} { set f [open $filename w] puts $f [my state] close $f } config proc load {filename} { set f [open $filename r] my state [read $f] close $f }
  • 22.
    Peculiaridades do XOTcl ● XOTcl tem caraterísticas diferentes do tradicional (C++/Java): ● Sistema de classes dinâmico. Tudo pode ser mudado a qualquer instante. ● É voltado aos objetos e não às classes, ou seja, cada objetos tem vida independente, podendo ter suas próprias “procs”, variáveis específicas do objeto, etc. ● É completamente reflexiva (um programa pode observar seu próprio comportamento e modificá-lo, se desejado).
  • 23.
  • 24.
    Classes e Objetos ● Uma classe generaliza operações e variáveis dos objetos (instâncias). Class Curso Curso instproc init args { my set pre-requisitos "" } Curso instproc sethorario hr { my set horario $hr } Curso historia -sethorario 10:30
  • 25.
    Precedência do next ClassTerrestre Class Maritimo Terrestre instproc desc args {return "-terrestre- [next]"} Maritimo instproc desc args {return "-maritimo-[next]"} Class Anfibio -superclass {Terrestre Maritimo} Anfibio instproc desc args {return "-anfibio-[next]"} Terrestre automovel Maritimo lancha lancha proc desc args {return "-lancha-[next]"} Anfibio hovercraft -terrestre- hovercraft proc desc args {return "-hovercraft-[next]"} -lancha—maritimo- -hovercraft--anfibio--terrestre--maritimo-
  • 26.
    Nested objects ● historia contains {Object idade_media} ● Class Point -parameter {{x 100} {y 300}} Class Rectangle -parameter {color} Rectangle r0 -color pink -contains { Rectangle r1 -color red -contains { Point x1 -x 1 -y 2 Point x2 -x 1 -y 2 } Rectangle r2 -color green -contains { Point x1 Point x2 } } ::historia::idade_media historia idade_media
  • 27.
    Filtros Object instproc exempFiltro{args} { puts "self = [self]" puts "calledproc = [self calledproc]" puts "args = $args" puts --------------------------- next } Class TesteClass TesteClass filter exempFiltro TesteClass umObjeto className instproc FilterName args { pre-part next post-part }
  • 28.
    Filtros (2) ● Filtros “por objeto” e “por classe” Class Painel Painel p1 Painel p2 Painel instproc observaFiltro args { puts "observaFiltro para objeto: [self]" set r [next] puts "observaFiltro (obj=[self]) retornou: $r" } Painel instfilter observaFiltro
  • 29.
    Mixins Class Agent Agent instproc move {x y} { # do the movement } Class InteractiveAgent -superclass Agent Class MovementLog MovementLog instproc move {x y} { # movement logging next } Class MovementTest MovementTest instproc move {x y} { # movement testing next } InteractiveAgent i1; InteractiveAgent i2 i1 mixin MovementLog i2 mixin MovementTest MovementLog
  • 30.
    Slots ● System slots: superclass, class, mixin, instmixin, filter, instfilter. ● Attribute slots. Class Person -slots { Attribute name Attribute salary -default 0 Attribute projects -default {} -multivalued true } Acessa o slot meta-objeto Person slot name Person rildo rildo name “Rildo Pragana” rildo name
  • 31.
    A função primitivaself self – retorna o nome do objeto em execução self class – retorna a classe que define a instproc corrente self proc – retorna a proc ou instproc em execução self callingclass – retorna a classe que chamou este método self callingobject – objeto que chamou este método self callingproc – a proc (ou método) que chamou o método corrente self calledclass – a classe que contem essa proc (mixins, filters) self calledproc – nome do método da proc alvo (só em filtros). self isnextcall – retorna 1 se chamado por “next” self next – retorna o path do próximo “next” self filterreg – em um filtro: retorna o nome da classe/objeto onde foi registrado na forma 'obj filter nomeDoFiltro' ou 'classe instfilter nomeDoFiltro' self callinglevel – nível da chamada self activelevel – nível da pilha onde a proc foi chamada
  • 32.
    Links interessantes ● http://www.pragana.net - Adventures in Linux Programming ● http://wiki.tcl.tk - Tcler's wiki (farta documentação!) ● http://www.tcl.tk - Tcl developer exchange ● http://media.wu-wien.ac.at - XOTcl homepage ● http://www.xdobry.de/xotclIDE/ - XOTclIDE homepage ● http://openacs.org - OpenACS (toolkit para aplicações web) ●
  • 33.