Utilizando ponteiros de função em PERL

Publicado julho 8, 2009 por samuca
Categorias: Perl

Tags: , , ,

Ponteiros de função são úteis quando precisamos ou desejamos dar um mesmo tratamento para funções ou métodos distintos. Seu uso é bastante difundido dentre programadores C/C++, o que ajuda na organização e reusabilidade de código, facilitando o gerenciamento de erros.

Em geral, programadores iniciantes costumam “fugir” dos ponteiros, porém, após uma compreensão de seu funcionamento básico, é possível perceber a sua empregabilidade em várias situações.

Neste rápido post, tentarei exemplificar o uso de ponteiros de função em PERL.

Como não definimos um tipo ao criar uma variável em PERL, basta adicionarmos uma variável qualquer, recebendo o nome da função que desejamos, e depois invocá-la, conforme exemplo abaixo:

#!/usr/bin/perl

use strict; # Comentar esta linha para rodar o primeiro exemplo

sub hello_world {
	print "Hello World!!\n";
}

sub call_function {
	my $function = shift;

	print "Invocando Funcao\n";

	&{$function}();

	print "Pronto!\n";
}

call_function("hello_world");

Perceba que apenas foi passado uma “string” para “call_function” contendo o nome da função desejada.

Até então vimos o quão fácil é invocar uma função através de um “ponteiro” para ela. O ponteiro não está explícito no código, porém, podemos perceber que através do “&” estamos referenciando o símbolo (função) referente a string passada.

Agora, se estivermos usando a diretiva “strict”, não poderemos trabalhar neste simples formato, pois o interpretador retornará o seguinte erro:

Can’t use string (“hello_world”) as a subroutine ref while “strict refs” in use at pointer.pl line 13.

Este problema ocorre pois, através da diretiva “strict”, todas as variáveis e funções utilizadas no script devem ser definidas no momento do seu carregamento. E no nosso exemplo anterior, como estamos passando apenas uma “string” como parâmetro para a função “call_function”, não é possível para o interpretador garantir que as variáveis e funções estão realmente implementadas no código.

Em geral, quando estamos utilizando ponteiros de função, sabemos quais serão as funções utilizadas pelo nosso programa, e desta forma, podemos definir um “hash” contendo todas as referências para as funções que iremos utilizar, para posteriormente estarmos invocando conforme a necessidade.

#!/usr/bin/perl

use strict;

my %function_table = (
	hello_there	=>	\&hello_there,
	print_name	=>	\&print_name
);

sub hello_there {
	my $name = shift;

	print "Hello $name!!\n";
}

sub print_name {
	my $name = shift;

	print "Nome Informado: $name\n";
}

sub call_function {
	my $function = shift;
	my $data = shift;

	print "Inicio\n";
	&{$function_table{$function}}($data);
	print "FIM\n";
}

call_function("print_name", "Samuel da Silva Feitosa");
call_function("hello_there", "Samuel");

Veja, que estamos utilizando a diretiva “strict” e que criamos um “hash” chamado “function_table”, onde definimos e referenciamos todas as funções que serão utilizadas pelo nosso programa. Perceba também, que a invocação da função mudou desde o nosso primeiro exemplo. Agora, ao invés de invocarmos diretamente a “string” contendo o nome da função, estamos buscando a referência dela informada no nosso “hash” de funções.

Para finalizar, note que neste exemplo passamos também um parâmetro para nossas funções, e estas manipularam de acordo com sua necessidade.

Este post visa apenas ilustrar o uso de ponteiros de função em PERL, e não cobre suas aplicabilidades. Quem sabe posteriormente eu escreva um pouco sobre isto.

Anúncios

Em que ordem as bibliotecas estáticas devem ser linkadas?

Publicado abril 17, 2009 por samuca
Categorias: C/C++, Tutoriais

Tags: , , ,

Após me deparar com alguns erros do linker, resolvi entender realmente o que eu estava fazendo ao linkar bibliotecas estáticas. Na verdade, o termo linkar talves não esteja totalmente correto, pois, ao gerar uma biblioteca estática, estamos fazendo nada mais do que juntar mais de um arquivo objeto em um único pacote, portanto, não estamos “linkando” a biblioteca, e sim carregando os símbolos nela dispostos.

No momento de linkar a biblioteca ao executável, o linker irá procurar em um arquivo (biblioteca) apenas uma vez, de acordo com a ordem passada na linha de comando.

Vejamos a um exemplo para facilitar a compreensão.

Vamos tomar como exemplo libA, libB e libC.
a.cpp

#include <iostream>

using namespace std;

void printA() {
	cout << "A" << endl;
}

b.cpp

#include <iostream>

using namespace std;

extern void printA();

void printB() {
	printA();
	cout << "B" << endl;
}

c.cpp

#include <iostream>

using namespace std;

extern void printB();

void printC() {
	printB();
	cout << "C" << endl;
}

Perceba que o arquivo fonte “a.cpp” é o mais básico (menor), e não depende de nenhum símbolo externo. Já o fonte “b.cpp” e “c.cpp” dependem de símbolos presentes em “a.cpp” e “b.cpp”, respectivamente.

Compilando:

g++ -c a.cpp
g++ -c b.cpp
g++ -c c.cpp

Após compilar os fontes acima, serão gerados os arquivos objetos de cada um. Agora vamos empacotar cada um em uma biblioteca estática.

ar -r libA.a a.o
ar -r libB.a b.o
ar -r libC.a c.o

Pronto, já temos nossas bibliotecas estáticas prontas para o uso. Vamos agora ver como ficaria o programa principal para utilizar estas bibliotecas:
main.cpp

extern void printC();

int main() {
	printC();

	return 0;
}

Perceba novamente, que o arquivo fonte “main.cpp” utiliza apenas a função “printC()”, que está declarada como externa. Agora vamos à compilação, e entender a “moral da história” que deu origem a este post.

Compilando:

g++ -o main main.cpp -lA -lB -lC -L.

Ao executar a linha de comando acima, o linker acusa o seguite:

./libC.a(c.o): In function `printC()':
c.cpp:(.text+0x7b): undefined reference to `printB()'
collect2: ld returned 1 exit status

E agora? O que muita gente não sabe (e eu também não sabia) é que o linker não carrega todos os símbolos presentes na biblioteca estática. O que ele faz, é, respeitando a ordem dos parâmetros de linha de comando, carregar os símbolos que estão definidos e sendo usados em cada arquivo fonte. Caso ele encontre algum símbolo (função) que ele desconheça, ele marca-o como “indefinido”, deixando para efetuar o carregamento depois. Mas perceba que o linker irá carregar da biblioteca estática apenas os símbolos utilizados anteriormente, ou seja, aqueles que foram marcados como “indefinidos”.

Caso alguma biblioteca passada como argumento na linha de comando após aquela que define determinado símbolo, solicite a inclusão do mesmo (símbolo), não fará com que o linker retorne na biblioteca anterior e o carregue.

É aí que está a grande confusão. Eu sempre imaginava o contrário disso, ou seja, que a ordem correta dos parâmetros deveria ser, definir primeiro os símbolos utilizados pelas bibliotecas subsequentes.

MAS NÃO! DEVEMOS FORNECER AO LINKER AS BIBLIOTECAS NA ORDEM DE MAIOR PARA A MENOR. Ou seja, fornecer primeiro as bibliotecas que utilizam os símbolos, para depois fornecer aquelas que o definem, pois o linker carrega somente os símbolos utilizados anteriormente.

Desta forma, conforme visto no exemplo acima, o linker acusou “undefined reference”, pois a “libC” utiliza o símbolo “printB()” que, na ordem na linha de comando, marcou-o com “indefinido” e nenhuma biblioteca subsequente o definiu.

O que aconteceu foi que o linker verificou os símbolos solicitados no arquivo fonte “main.cpp”. Lá ele percebeu o uso da função externa “printC()”, que até então não havia sido definida, e marcou-a como “indefinida”. Passando a verificar a “libA.a”, ele verificou todos os símbolos presentes nela, e constatou que nenhum havia sido utilizado até então. Portanto, não carregou nenhum símbolo. Na sequência, foi verificado a “libB.a”, que também não possuia nenhum símbolo utilizado, fazendo com que o linker novamente não carregasse nenhum símbolo. Por fim, o linker verificou a biblioteca “libC.a”, percebendo que o símbolo “printC()” estava sendo referenciado (pelo “main.cpp”), e estava marcado como “indefinido”. Desta forma, ele carregou o símbolo “printC()”. Porém, a função “printC()” utiliza o símbolo “printB()”, que até então, não foi definido. Neste ponto, o linker finalizou a verificação em todas as bibliotecas informadas, e percebeu que o símbolo “printB()” continua indefinido após a verificação de todas as bibliotecas. Portanto, está aí o motivo do “undefined reference” visto acima.

Uma compilação correta seria:

g++ -o main main.cpp -lC -lB -lA -L.

Fazendo, desta forma a com que o linker enxergue os símbolos que estão sendo usados dentre as bibliotecas fornecidas.

Sei que a explicação parece um pouco confusa, e talves eu não tenha conseguido ser claro o suficiente. Mesmo assim, vale como uma base para quem precisar.

Threads em C++ no Linux

Publicado fevereiro 17, 2009 por samuca
Categorias: C/C++, Dicas, Linux

Tags: , ,

Uma thread é como uma linha de execução de um programa, que executa “paralelamente” com o restante do código do programa. A idéia é, a partir do ponto desejado, criar uma espécie de processo filho, que compartilhe os recursos com o programa pai. Porém, não é como a chamada “fork()”, que duplica o processo completo que está em execução. Em geral, o programa não executa “paralelamente”, tendo em vista que os computadores pessoais em geral, possuem apenas um processador. Mesmo assim, o escalonador de processos, dá a impressão de que os trechos de código estão realmente rodando em paralelo. No caso de computadores com mais de um processador, ou mais de um “core”, estes trechos de código podem realmente estar executando paralelamente.

O código que será mostrado aqui está longe de ser completo, mas vale para exemplificar o encapsulamento das chamadas básicas em uma classe.

Header

#ifndef THREAD_H
#define THREAD_H

#include <pthread.h>

class Thread {
        public:
                Thread();
                ~Thread();

                void Start();
                void Wait();
                void Abort();
                void Detach();

                pthread_t GetId();

        protected:
                static void *entryPoint(void *pthis);
                virtual void run() = 0;

        private:
                pthread_t m_threadId;
};

#endif

Implementação

#include "thread.h"

Thread::Thread() {
}

Thread::~Thread() {

}

/* static */
void *Thread::entryPoint(void *pthis) {
        Thread *ptr = static_cast<Thread *>(pthis);
        ptr->run();
}

void Thread::Start() {
        int nRet;

        if (pthread_create(&m_threadId, NULL, entryPoint, this) != 0) {
                // throw an error
        }
}

void Thread::Wait() {
        if (pthread_join(m_threadId, NULL) != 0) {
                // throw an error
        }
}

void Thread::Abort() {
        if (pthread_cancel(m_threadId) != 0) {
                // throw an error
        }
}

void Thread::Detach() {
        if (pthread_detach(m_threadId) != 0) {
                // throw an error
        }
}

pthread_t Thread::GetId() {
        return m_threadId;
}

Encapsulamento da classe

A classe Thread acima apresentada, implementa internamente as chamadas à biblioteca pthread, realizando todo o processo de criação e manipulação da thread transparentemente.

Note que o método “entryPoint” é estático, para que seja possível passá-lo como ponteiro de função para chamada “pthread_create”, e que ele recebe como parâmetro o argumento “this”, que representa a instância do objeto da thread.

A modelagem da classe segue a ideia da classe Thread da API da linguagem Java, ou seja, para a implementação de threads, deve-se escrever uma nova classe, que herde da classe Thread, e implemente o método “run()”, que será o ponto de entrada da nova thread

Exemplo:

#include <iostream>
#include "thread.h"

using namespace std;

class SimpleThread: public Thread {
        private:
                void run() {
                        cout << "Este codigo esta rodando ";
                        cout << "em uma nova thread" << endl;
                        sleep(5);

                        cout << "Finalizando a execucao da thread" << endl;
                }
};

Como pode ser visto acima, a classe SimpleThread implementa o método “run()”, que a partir de então roda em uma nova thread.

Funções utilizadas (pthread)

Para quem nunca programou threads em C, utilizei a biblioteca pthread, que fornece uma API para utilização de threads. Em seguida, vou explicar sucintamente a utilização de cada uma das chamadas utilizadas no código mostrado acima.

pthread_create:

Protótipo:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);

Esta chamada, inicia uma nova thread, e invoca a chamada repassada em “start_routine”, passando “arg” como argumento.

Parâmetros:

thread:Endereço de memória para retornar o identificador da thread.
attr: Estrutura que contém atributos para a utilização na thread. Caso seja informado NULL, assume os atributos padrões.
start_routine:Ponteiro de função, a partir de onde será iniciada a nova thread.
arg: Parâmetro que será repassado para a função “start_routine”.

pthread_join:

Protótipo:

int pthread_join(pthread_t thread, void **retval); Esta chamada espera até que a thread especificada no primeiro argumento finalize.

Parâmetros:


thread:
Identificador da thread.
retval: Se este parâmetro não for nulo, copia os dados retornados pela thread criadora.

pthread_cancel:

Protótipo:

int pthread_cancel(pthread_t thread);

Envia uma requisição de cancelamento para a thread. O atendimento ou não desta requisição, está atrelado aos atributos de inicialização da thread.

Parâmetros:

thread:
Identificador da thread.

pthread_detach:

Protótipo:

int pthreada_detach(pthread_t thread);

Esta chamada libera os recursos associados à thread automaticamente assim que ela é finalizada.

Parâmetros:

thread:
Identificador da thread.

Para mais detalhes, consulte as man pages da biblioteca pthread.

Como pode ser notado, o código aqui apresentado está incompleto, e não tem o intuito de ser uma referência única no uso de threads. Porém pode servir como uma idéia de design inicial para uma classe mais completa.

Criando bibliotecas dinâmicas em C

Publicado outubro 17, 2008 por samuca
Categorias: C/C++, Linux, Tutoriais

Tags: , , ,

Muitas vezes temos a necessidade de incluir bibliotecas dinâmicas de terceiros em nossos programas. Este já é um processo consideravelmente comum para quem desenvolve software.

Porém algumas vezes, precisamos ou desejamos ser os produtores destas bibliotecas, para que outros possam utilizar nossas bibliotecas, ou mesmo para “modularizar” ou “desacoplar” parte do código do executável principal.

Desacoplar parte do software é algo desejável, tendo em vista que pode-se modificar o tratamento de funções dentro de uma biblioteca dinâmica, deste que não modifique-se a interface, sem a necessidade de recompilação do executável principal.

Grandes projetos, tendem a possuir várias bibliotecas dinâmicas, facilitando o desenvolvimento por grupos de programadores em paralelo, acelerando o processo como um todo.

Também é possível a carga da biblioteca dinâmica em tempo de execução do programa através da “libdl”, porém, isto fica para um próximo post.

Linkando uma biblioteca em um programa qualquer:

samuel@samuel ~/testes/c $ gcc main.c -o main -lpthread

O que acontece, é que quando passamos o parâmetro “-l<biblioteca>” para o “linker”, o mesmo, procura nos diretórios padrões do sistema, por um arquivo chamado “lib<biblioteca>.so.<versao>”, carregando ele na inicialização do programa.

Estas bibliotecas, tem de ser carregadas de algum local no sistema de arquivos. Este local, geralmente é “/lib”, “/usr/lib” ou “/usr/local/lib”, de acordo com os padrões definidos pela GNU.

Adicionando caminhos de busca a bibliotecas:

Também é possível adicionar locais a serem buscadas as bibliotecas, possibilitando o carregamento de bibliotecas que estejam fora dos caminhos padrões.

Existe o arquivo “/etc/ld.so.conf” que contém uma lista de diretórios extras com “shared objets”, o qual pode ser editado, informando-se novos caminhos.

Após a edição deste arquivo, é necessário recarregar o “cache” de bibliotecas, o que pode ser feito através da execução do programa “ldconfig”.

Outra forma de adicionar caminhos para “shared objects” é através da variável de ambiente “LD_LIBRARY_PATH”, que pode conter um lista de diretórios separados por vírgula. Geralmente, a alteração desta variável de ambiente se dá apenas em tempo de desenvolvimento.

Criando uma biblioteca dinâmica

Código “simple.c”:

#include <stdio.h>

void show_hello(void) {
	printf("Hello World!!!");
}

Compilando como uma “shared object”:

samuel@samuel ~/testes/c $ gcc -fPIC -shared -g simple.c -o simple.so

Opções passadas para o GCC:

-fPIC: Faz com que se gere um biblioteca com código “Position-Independent”. Ou seja, o código objeto gerado pode ser posicionado em qualquer área de memória de um programa que venha a incluir esta biblioteca.

-shared: Indica que deve-se gerar um “shared object”.

-g: Habilita informações de depuração. Fazendo com que seja possível utilizar um debugger para facilitar a detecção de erros.

Código “main.c”:

int main() {
	show_hello();
}

Compilando com a “shared object”:

samuel@samuel ~/testes/c $ gcc -o main main.c ./simple.so

Desta forma, a biblioteca “simple.so” vai ficar ligada através do seu caminho relativo (./simple.so), que neste caso, é o mesmo diretório, não sendo necessário a alteração dos caminhos de busca das bibliotecas dinâmicas.

Visualizando as dependências de um programa

Para exibir uma lista das bibliotecas dinâmicas que um programa precisa, basta utilizar o utilitário “ldd”.

samuel@samuel ~/testes/c $ ldd main
     linux-gate.so.1 =>  (0xb7fa1000)
     ./simple.so (0xb7f9e000)
     libc.so.6 => /lib/libc.so.6 (0xb7e55000)
     /lib/ld-linux.so.2 (0xb7fa2000)

É claro que há muito mais a falar sobre bibliotecas dinâmicas. Pretendo voltar a escrever mais sobre isto em breve.

Instalando o DBDesiner no Gentoo Linux

Publicado janeiro 28, 2008 por samuca
Categorias: Dicas, Linux

Normalmente, no Gentoo é só pensar no que se quer baixar, e digitar “emerge -av <nome_programa>”. Porém, o ebuild do DBDesigner não foi mantido nos repositórios do Portage. Portanto, caso seja necessário usá-lo, pode-se instalar desta forma:

Primeiramente, é necessário efetuar o download do pacote que contém os binários compilados do DBDesigner, no site oficial:

http://fabforce.net/downloads.php (Baixar o pacote “.tar.gz”)

Após isto, basta descompacta-lo em um diretório qualquer, e o DBDesigner já estará instalado, para tal:

Movendo o pacote para o diretório da instalação:

mv ~/DBDesigner4.0.5.4.tar.gz /opt/

Descompactando:

cd /opt/
tar -zxsf DBDesigner4.0.5.4.tar.gz

Após estes passos, a instalação do DBDesigner está completa, porém, ao tentar executa-lo, será notada a falta da “libborqt-6.9-qt2.3.so”. Portanto, devemos instalar o pacote que possui esta lib, e para isto podemos usar o emerge.

O pacote se chama “kylixlibs3-borqt”, e é mascarado por “default”. Para instalarmos, basta executar:

ACCEPT_KEYWORDS=”~x86″ emerge -av kylixlibs3-borqt

Agora sim, é possível usar o DBDesigner.

Configurando o Horário de Verão no Linux

Publicado outubro 29, 2007 por samuca
Categorias: Dicas, Linux

Sabendo-se que no Brasil os horários de verão não possuem dias fixos para início e fim no calendário, devemos, a cada ano que passa, ajustar manualmente nosso TimeZone. Para fazer isso no Linux é relativamente simples.

Primeiro devemos criar um arquivo informando as regras, que indicam o início e fim do horário de verão.

Criaremos então um arquivo qualquer e com a seguinte sintaxe (campos separados por tabulação):

Rule    <nome>    <de>    <para>    <tipo>    <mes>    <dia>    <hora>   <hora_dif>       <letra>
Rule    <nome>    <de>    <para>    <tipo>    <mes>    <dia>    <hora>   <hora_dif>       <letra>

Sendo:

Nome: Nome da regra.
De: O primeiro ano em que a regra se aplica.
Para: O último ano em que a regra se aplica.
Tipo: Caso informado “-“, se aplica a todos os anos entre “de” e “para”.
Mes: Mes de início da regra.
Hora Dif: Diferença no relógio que deve ser aplicada.
Letra: Letra indicando como a regra deve aparecer no comando date.

Seguindo, no mesmo arquivo, devemos ter outra linha para a Zona, com o seguinte formato:

zone    <path>    <diff_utc>   <regra>    <formato>

Sendo:

Path: Caminho e Nome do TimeZone a ser aplicado.
Diff UTC: Diferença de tempo entre o UTC e o tempo local.
Regra: A regra a qual se aplica.
Formato: Usado para mostrar a “letra” indicada nas regras acima.

Exemplo:

Rule    BrazilSP    2007    only    –    Oct    14    00:00    01:00    S
Rule    BrasilSP    2008    only    –    Feb    16    00:00    00:00    –
zone    America/Sao_Paulo    -3:00    BrazilSP    BR%sT

As duas primeiras linhas indicam, respectivamente, início e fim do horário de verão.
Na terceira linha, vemos “BR%sT”, sendo que o “%s” será substituído pela letra indicada na primeira regra, ficando então “BRST”, ou seja, Brazilian Saving Time.

Após criado o arquivo, devemos gerar o arquivo de “localtime”, utilizando o aplicativo “zic”.

Basta fazer:

zic <nome_do_arquivo_criado>

Após isso, será gerado o arquivo informado em “Path”, na raiz “/usr/share/zoneinfo”. Sendo assim, será gerado o arquivo Sao_Paulo na pasta “/usr/share/zoneinfo/America”.

Após feito isso, basta sobrescrever o arquivo “/etc/localtime”, pelo nosso arquivo gerado.

O horário de verão para este ano estará sendo respeitado. No próximo ano, é necessário refazer o processo modificando as datas de início e fim.

Configurando a inicialização em um Sistema Debian Linux

Publicado outubro 23, 2007 por samuca
Categorias: Dicas, Linux

Para as distros da família Red Hat, eu utilizava o comando “chkconfig” para gerenciar a inicialização do sistema. Porém, no Debian, este programa não existe. Então, seu “substituto” é o “update-rc.d”, que como o chkconfig, insere/remove programas no startup do Linux.

Utilização (como root):

Adicionando programas na inicialização:

~$ update-rc.d <script> defaults

ou, configurando sua ordem na inicialização, e seu “runlevel”:

~$ update-rc.d <script> start <ordem> <runlevels> . stop <ordem> <runlevels> .

Exemplo:

~$ update-rc.d proftpd defaults

Isto faria a inicialização “default” do servidor de ftp.

~$ update-rc.d proftpd start 80 2 3 4 5 . stop 80 0 1 6 .

Este comando faria a inicialização do servidor de ftp com ordem 80, nos “runlevels” 2, 3, 4, 5 e desativaria a inicialização com ordem 80, nos “runlevels” 0, 1, 6.

Usando as opções default, a ordem de inicialização é 20, e os “runlevels” são os mesmos informados acima.

Removendo programas da inicialização:

~$ update-rc.d -f <script> remove

Exemplo:

~$ update-rc.d -f proftpd remove

Este comando realiza a remoção da inicialização do servidor de ftp perante o sistema.