Inclua códigos-fonte de outras linguagens dentro do seu script Perl
Colaboração: Otávio Fernandes
Data de Publicação: 29 de janeiro de 2008
Introdução:
O Inline é um módulo que permite que você acrescente código de outras linguagens de programação diretamente no seu script Perl, salvando-o de ter que escrever dois programas e fazê-los "conversar", gastando muito mais tempo do que se você pudesse simplesmente misturar as linguagens ... mas com a flexibilidade do Perl e a ajuda do Inline você pode. Nas linhas abaixo estarei demonstrando de forma descontraída e objetiva como isso é possível.
Fazendo a Instalação:
Antes de fazermos uso do Inline, temos que fazer a instalação, para isso separei duas formas de realizá-la; uma via CPAN, a qual eu recomendo, pois é muito mais fácil centralizar os pacotes do Perl em uma única ferramenta, e também podemos ter sempre a versão mais nova de cada módulo, o que nem sempre acontece com os pacotes pré-compilados; e outra via apt-get:
CPAN:
Com a mesma simplicidade dos códigos em Perl, utilizamos a CPAN: Neste primeiro passo, chamamos o prompt para execução de comandos:
perl -MCPAN -e shell
Logo em seguida devemos requisitar a instalação do módulo Inline:
install Inline
Pronto. Observe os retornos e se necessário, trate os erros que aparecerão no meio do caminho. Não entenderei mais esta parte pois este não é o nosso foco.
Debian:
No Debian, com a utilização do apt-get, as coisas ficam tão fáceis quanto na CPAN, basta executar o seguinte comando (como root, ou com permissões de super-usuário):
# apt-get update # apt-get install libc-scan-perl libinline-octave-perl libinline-perl libtest-inline-perl
E esperar o retorno do comando, aqui nos meus testes eu não tive nenhum problema com os dois tipos de instalação.
Exemplos Práticos:
Em um determinado momento da nossa vida de programadores, seja profissionalmente ou apenas por diversão, fez-se necessário a execução de algum(s) método(s) de uma biblioteca natural de outra linguagem, o que para alguns casos, é aparentemente inviável, mas com a flexibilidade do Perl, e as inovações dos módulos presente na CPAN isso é mais do que possível, é fácil e muito prático. Nos exemplos abaixo, estaremos chamando métodos da nossa "libteste", a qual está presente no diretório "/usr/lib" e tem seus headers no diretório "/usr/include", o teste.h, para dificultar as coisas, quando instânciamos a libteste, precisamos ter no nosso fonte declarado uma estrutura, a qual servirá para troca de dados, o nome dela é treetst (bem sugestivo :-P):
Utilizando o Inline C, podemos fazer uso das funções de duas formas distintas:
- Escrevendo um trecho de código C que faça a chamada da função, e retorne seu conteúdo para o nosso script:
01| #!/usr/bin/perl 02| 03| use scrict; 04| use warnings; 05| 06| # fazendo a chamada direta da função escrita no código abaixo 07| my $retr = WrapFTest(); 08| 09| # imprimindo na stdout o retorno da função WrapFTest 10| print $retr, "\n"; 11| 12| # declarando a nossa libteste como parâmetro para compilação 13| use Inline C => Config => ENABLE => AUTOWRAP => LIBS => '-lteste'; 14| # da próxima linha até a string "END_OF_C_CODE" tudo é código C 15| use Inline C => << 'END_OF_C_CODE'; 16| 17| #include <teste.h> 18| 19| struct treetst *p1, *p1; 20| 21| int WrapFTest () { return Teste(); } 22| 23| END_OF_C_CODE
Segue o comentário das linhas mais importantes deste código, na mesma organização que o interpretador e o Inline o fazem: [16-22] Junção deste código à trecho pré existente de código C, preparado para o enxerto de novas linhas de código. Atente que o código tem todos os requisitos para compilar a executar a libteste, ou seja, a presença do "include" de seu header "teste.h" e também apresenta da estrutura "treetst", necessária para troca de dados (não tratados aqui); [13] Configurando como será a compilação do código C, com o uso da "-lteste" junto com o gcc, esta linha que permite ao compilador saber qual biblioteca estamos procurando. Para maiores detalhes, execute o comando "# ldconfig -v" e faça uma breve análise dos resultados retornados; [07] Fazendo a execução da função "WrapFTest()", a qual tem o papel de intermediar a execução da função que nos interessa, a "Teste()". Fazemos uso desta função porque não temos acesso direto à libteste, apenas ao pseudo-código que geramos no bloco de linhas 16 a 22; [10] Imprimindo o retorno da função "Teste()". Lembrando que o retorno, ou parâmetros, ou até estruturas de dados podem trocados entre o script e o código C (outras linguagens também). Pronto, executamos uma chamada na libteste através do nosso pequeno, porém eficiente, código ANSI C, veremos no próximo exemplo como fazer isso de forma direta. - Podemos instânciar as funções diretamente da biblioteca e fazer uso no nosso script:
01| #!/usr/bin/perl -w 02| 03| use warnings; 04| use strict; 05| 06| use Inline C => Config => ENABLE => AUTOWRAP => LIBS => "-lteste"; 07| use Inline C => q{ struct treetst *p1, *p2; }; 08| use Inline C => q{ int Teste(); }; 09| 10| my $retr = Teste(); l1| 12| print $retr, "\n";
Neste exemplo estamos acessando a libteste diretamente do nosso script em Perl, sem a ajuda de código para enxerto, apenas com o protótipo das funções (vide o arquivo header para maiores detalhes). Segue o comentário e explicação das linhas mais influentes do nosso script: [07] Declarando a estrutura que vamos utilizar para trocar os dados com a libteste, assim como fariamos em um código C comum (vide Caso 1); [08] Protótipo da função "Teste()", presente no header "/usar/include/teste.h"; [10] Eureca. Estamos acessando a função "Teste()" diretamente do nosso script :-); [12] Imprimindo na saída padrão o retorno da função "Teste()";
Bibliografia:
- http://search.cpan.org/~ingy/Inline-0.44/Inline.pod
- http://search.cpan.org/~ingy/Inline-0.44/C/C.pod
- http://search.cpan.org/~ingy/Inline-0.44/C/C-Cookbook.pod
Otávio Fernandes, exercendo atualmente o cargo Programador Sênior e Gerente de Projetos, tem larga experiência em appliances para servidores de E-Mail e Anti-SPAM, fluência em linguagens como ANSI C e C++, porem um aprendiz em Perl. Contato otaviof at gmail dot com.