Removendo o uso de ponteiro de ponteiro de funções

O uso de ponteiros de ponteiros é uma forma de armazenar estrutura bidimensionais (uma matriz por exemplo) ou quando se deseja atualizar o valor de um ponteiro.
O primeiro caso, é uma ótima forma de representar estruturas bidimensionais, mas o segundo caso deve ser evitado.
Por que evitar o segundo caso? Você terá que se preocupar com acesso ao conteudo usando o operador *, isso deixará seu código menos legível, uma vez que você poderá ter que usar parenteses para indicar a precedência do operador * sobre o operador ->, um código eu seria algo como ptr->k = ptr->k+10 passa a ser (*ptr)->k = (*ptr)->k+10.
Essa falta de legibilidade trás também uma complexidade e pode trazer também confusão, uma vez que você passa a trabalhar com um apontardor para um apontador de onde está a sua estrutura.
Essa forma de acesso indireto é mais lenta que o acesso direto, uma vez que será necessário primeiro descobrir o endereço onde está o ponteiro, depois com esse endereço acessar a estrutura no endereço indicado pelo ponteiro.
Uma forma bastente utilizada do ponteiro de ponteiro é o seguinte
{    …
  MeuTipo * ptr = NULL;
  criaTipo(&ptr)
    …
}
e a função que recebe o endereço do ponteiro:
void criaTipo(MeuTipo ** pdp){    …
  (*pdp) =  (MeuTipo*) malloc ….;
    … inicializa dados em pdp usando (*pdp)
}
O que esse trecho de código faz é uma inicialização de um ponteiro, mas você pode considerar que ptr não apontava para NULL mas para o início de sua lista ligada ou para a raiz de sua árvore enraizada e a função criaTipo irá incluir um novo elemento na sua árvore ou lista (o que pode mudar o apontador).
Temos 3 pontos básicos: Primeiro a chamada da função criaTipo que recebe como parâmetro o endereço do ponteiro ptr (operador &). Veja que ele possui um valor nulo, mas ainda assim possui um endereço válido, uma vez que um ponteiro é uma variável (que armazena endereços de memória) e esse ponteiro está em algum lugar da memória.
Segundo ponto é a inicialização de um espaço de memória (o malloc) que será armazenado no ponteiro que teve seu endereço passado como parâmetro (nessa caso o endereço para o qual ptr apontava é substituido pelo endereço alocado).
O terceiro ponto que é a inicialização dos valores da estrutura (pode ser apontar prox para null) que deve ser feito usando o acesso ao conteudo do ponteiro de ponteiro (*pdp).
Podemos modificar o código para que não seja mais necessário passar o ponteiro de ponteiro (e com isso tornar mais legível o código). Primeiro vamos mudar a função criaTipo trocando o parâmetro de ponteiro de ponteiro para um ponteiro simples e mudando o seu retorno também.
MeuTipo * criaTipo(MeuTipo * pdp) {
    ….
Com essa alteração, é esperado o seguinte comportamento:
Se houve a necessidade de alterer o valor para o qual o ponteiro original apontava, esse novo valor deve ser retornado, se não houve mudança, então o valor anterior (pdp) deve ser retornado.
Para o caso de alocação de memória como o caso anterior:
MeuTipo * criaTipo(MeuTipo * pdp) {
  pdp = (MeuTipo*) malloc ….
    … Inicializa dados em pdp
  return pdp;
}
Veja que agora não será mais necessário usar o operado * e nem (* ). e agora existe um return que retorna o endereço criado.
o código completo do exemplo anterior fica:
{    …
  MeuTipo * ptr = NULL;
  ptr = criaTipo(ptr)
    …
}
e a função que recebe o endereço do ponteiro:
MeuTipo* criaTipo(MeuTipo * p){    …
  p = (MeuTipo*) malloc ….
    … Inicializa dados em p
  return p;
}
Para exemplificar, uma inserção ordenada em uma lista ligada poderia ser algo como
Lista* criaTipo(Lista * ptr, int valor){
  se (ptr == NULL){     //lista vazia
    ptr = (MeuTipo*) malloc ….
    … Inicializa valor em ptr
    return ptr;
  }
  senão{     //Lista não vazia
    Lista * lTmp = malloc …
    … Inicializa valor em lTmp
    se (lTmp->n < ptr->n){   //insere no começo da lista
lTmp->prox = ptr
return lTmp;
    }senão {
      …
      Trata outros casos de inserção em uma lista
    }
  }
  return ptr;
}
Veja que podem ser retornados: um novo valor caso a lista esteja vazia (ptr = (MeuTipo*) malloc), uma novo valor caso a lista não esteja vazia mas o valor deve ser inserido no começo da lista (return lTmp;), ou pode ser retornado o mesmo valor de ptr (return ptr;).
Se ficarem com dúvidas, deixe um comentário

Proposta do GSoC aceita! Valeu KDE

Dear Wagner,

Congratulations! Your proposal “Rocs support to others Data structure, scripts include and new file format support.” as submitted to “KDE” has been accepted for Google Summer of Code 2010….

Recebi esse e-mail da equipe do GSoC segunda e fiquei muito feliz com a aprovação. Mas antes de comemorar, tem algumas pessoas me perguntando o que é GSoC e como eu consegui isso. De lambuja vou falar do meu projeto 🙂

Primeiro o GSoC (Google Summer of Code) é um projeto onde estudantes trabalham no verão (do hemisfério norte) em projetos de software livre e são remunerados por isso.

Para participar, o estudante deve escrever um projeto no qual descreve o que ele desenvolverá (ou organizar também, um aplicativo não é só código 🙂 ) para uma determinada entidade, que no meu caso foi o KDE. Esse projeto é enviado para o apreciação dos participantes da entidade onde eles votam nas proposta indicando se a mesma deve ser aceita ou não. Ao final um certo número de projetos são aceitos pela entidade e enviados para o Google. O mesmo efetua uma analise sobre esses projetos selecionados e comunica os indicados.

O GSoC é visto por muitos como uma forma de aumentar a rede de contatos e se preparar para o mercado de trabalho, uma vez que o projeto deve ser cumprido e existem prazos a cumprir. Alguns que participaram de edições anteriores passam a agir como mentores. Mentores são pessoas da entidade que auxiliam os alunos a cumprir a tarefa, mas não escrevem nada apenas tiram dúvidas.

Segundo, para mim conseguir a aprovação eu digo que foi em grande parte pelos prévio contato com o projeto, uma vez que eu pude conversar e propor melhorias que melhorariam o projeto e, com isso, consegui captar o que o projeto precisava antes mesmo de pensar em GSoC (que eu nem tinha idéia de participar a poucos meses), e assim escrever uma proposta que tivesse mais chace de ser aprovada

um pouco de história agora:

Nos idos do ano de 2009 do nosso senhor, vim a conhecer algo que veio a acelerar o meu labor como desenvolvedor. Eu acredito, hoje, que o que vim a encontrar naquele tempo seja o Graal dos frameworks para aplicações, poís minha capacidade de desevoldedor aumentou por demais no tempo transcorrido até hoje.

Após consultar o oráculo para mais saber sobre tal frameworke, vim a ser indicado a ler manuscritos, hoje destruidos pela ação do seu dono, onde era explicado sobre como operar tal ferramenta. Então, vejo algo totalmente inesperado e até aquele momento para mim impossível a não a Hercules e seu panteão, mas ví, uma aplicação onde era possível de se criar grafos e interagir com os mesmos usando de scripts, tudo isso em tempo de execução!

Busquei pelos reinos sobre a pessoa que criou aquilo tendo a encontrado reunindo um rebanho juntamente com outros pastores vivendo tranquilamente. Mas me mantive a distância, apenas ouvido seus sermões de conhecimento supreendentes e regozijei-me com suas colocações. Por volta do primeiro mês do inverno, decidi tentar um contato com ele, para saber se ele deseja ajuda com o seu filho, tendo como resposta uma afirmativa. Passei a assistir o crescimento de tal filho, mas mantendo uma certa distânia e apenas indicando ao pai os erros cometidos pelo seu filho. E foi assim até o inicio do verão, quando eu estava preparando algums scripts, ouvi uma resposta após indicar mais uma das peripécias do filho que me fez agir: “Pare de relatar bugs se pode corrigir”. Com isso passei a ajudar diretamente na criação do filho aplicando as devidas correções quando necessário.

Esse ano, como já estava contribuindo com o Rocs, começei a propor algumas possiveis melhorias e implementei algumas, como por exemplo o suporte a plugins de ferramentas, onde é possível rodar algoritmos em C++, por exemplo, sem conhcer quase nada sobre a API do Rocs ou do KDE e o suporte a formatos de arquivos.

Como eu já vinha contribuindo para o projeto, isso aumentou em muito as minhas chances de ser aceito.

Sobre o projeto, eu demorei demais escrevendo, assim fiquem com o resumo, depois explico melhor http://www.socghop.appspot.com/gsoc/student_project/show/google/gsoc2010/kde/t127230762382

Propriedades dinamicas e ‘coisas mais’

Nos ultimos dias Tomaz e eu estamos trabalhando para adicionar algumas features novas no Rocs e corrigindo alguns bugs que aparecem no caminho.

Conseguimos terminar a adição de propriedades dinâmicas, propriedades estas que podem ser adicionadas e utilizadas durante o script. Com elas fica mais fácil trabalhar com alguns problemas de grafos, como por exemplo PRV, CCP, CCCP, e outras siglas legais, uma vez que se podem adicionar propriedades como por exemplo capacidade ou demanda diretamente nos nós, sem ter um vetor separador. Aqui tem uma imagem
Rocs: Now with dinamic properties

Pra quem conhece o Rocs deve ter reparado que os icones dos nós estão diferentes neh? Bom, essa é uma outra novidade (ainda em desenvolvimento) que é os icons pack, onde os usuários podem criar seus prórpios conjuntos de icones (para apresentar sobre VRP, pode colocar o deposito como um prédio e as demandas como lojas, por exemplo) sendo interessante para apresentar em palestras

Foram feitas algumas melhorias para estabilidade no core e alterações na interface.

Se quiserem testar essa versão do rocs, o código fonte pode ser obtido com o svn (svn co svn://anonsvn.kde.org/home/kde/trunk/KDE/kdeedu/rocs)

O inicio antes do fim

Por volta de julho contatei o Tomaz para ajudar no desenvolvimento do Rocs. Mas devido a ‘medo’ e falta de tempo mesmo (quem manda se envolver com tudo) não tinha pego o projeto pra trabalhar.

Após alguns meses o Tomaz pediu pra mim escrever uns exemplos para o Rocs, claro que aceitei, até pq eu jah tava com vergonha de por me dispor a ajudar e não ter posto o mão na massa ainda.
Devido a um erro em um script, encontrei um bug que fazia o Rocs travar. A resposta do Tomaz: Não abra bugs que pode corrigir:) . não poderia ter sido melhor. decidi que devia resolver.

Depois de lutar um pouco com threads, conseguimos (o Tomaz me deu uma baita mão pelo Gtalk ) e agora posso dizer que sou um ‘colaborador’ do KDE (através do Rocs).

E consegui antes do final do ano inciar a ajudar esse grande projeto que é o KDE através do Rocs, o qual tem várias idéias por serem implementadas para uma próxima versão e que vou ajudar nisso.

web service com Qt, Qxt e qtSoap

Como uma tarefa de uma disciplina era desenvolver um web service simples o professor disse ‘Façam em Php como está no artigo que voces leram’. Mas bem, eu teria que instalar um servidor, configurar apache, fazer XMLSchema… Eu ia demorar mais tempo executando o setup do sistema.

Pra variar eu tenho que tentar sempre fazer as coisas usando Qt. Com uma breve busca no google, encontrei essa entrada para o lado servidor e essa outra para o lado cliente, ambas no blog QtEffort, muito bons posts (e os temas do blog tambem).

Primeiro vou dizer o que meu web service deve executar:
-Verificar se um usuário já está cadastrado em um BD;
-Cadastrar um novo usuário.
Bem simples, mas pretendo usar ele como base para incrementar uma aplicação para S60 colocando records online.

Bom o que tive que alterar nos códigos disponibilizados no QtEffort:

-Implementar o parser para tratar os pedidos SOAP;
-conectar em BD para buscar/cadastrar um novo usuário;
-construir mais de uma mensagem no cliente (verificar existencia/inserir usuário).

Vamos aos códigos, para facilitar eles estão no github.

No lado cliente temos agora essas funções para verificar se o cliente já está connectado e outra para criar um novo usuário com senha. Basicamente o que é feito é criar uma mensagem SOAP (usando a libQtSOAP) uma com o metodo ExistLogin e outra com o metodo CreateUser. O objeto http é do tipo QtSoapHttpTransport que cuida de toda parte de envio dos dados. O sinal QtSoapHttpTransport::responseReady() é connectado ao slot Client::getResponse().

void Client::checkLogin(QString login){
   QtSoapMessage request;
   request.setMethod("ExistLogin");
   request.addMethodArgument("login", "", login);
   http.submitRequest(request, "/add/");
}
void Client::createUser(QString login, QString pass){
   QtSoapMessage request;
   request.setMethod("CreateUser");
   request.addMethodArgument("login", "", login);
   request.addMethodArgument("pass", "", pass);
   http.submitRequest(request, "/add/");
}
void Client::getResponse(){
   const QtSoapMessage &msg = http.getResponse();
   if (msg.isFault()) {
     qDebug("Error: %s", qPrintable(msg.faultString().toString()));
   }
   emit response(msg.returnValue().toString());
}

Como podem ver não tem nada de outro mundo (como a maioria das coisas em Qt). Para o lado do servidor temos:

QString WebService::createUser(QString user, QString pass){
  QSqlQuery q ;
  if (checkLogin(user) == "Exist"){
    return QString("User allready exist!");
  }
  q.prepare("insert into users values(:a, :b)");
  q.bindValue(":a",user);
  q.bindValue(":b",pass);
  if (q.exec()){
    return QString("Inserted!");
  }
  q.finish();
  return QString("Sorry, Database error: " + q.lastError().text());
}

A função que cria um usuário gerando uma QString com o resultado. Esse resultado é que será enviado como resposta para o cliente.

A outra função alterada é a que trata os dados recebidos. Ela que trata do recebimento das informações do cliente e decide qual processamento deve ser executado.

void WebService::indexRequested(QxtWebRequestEvent *event){
  qDebug() << "Request Headers: ";
  if (event->method.compare("POST")==0) {
    QxtWebContent *myContent = event->content;
    qDebug() << "Bytes to read: " << myContent->unreadBytes();
    myContent->waitForAllContent();
    QByteArray requestContent = myContent->readAll();

    //Parse SOAP XML
    SimpleSoapParser handler;
    QXmlSimpleReader reader;
    reader.setContentHandler(&handler);
    reader.setErrorHandler(&handler);
    QBuffer xml(&requestContent);
    QXmlInputSource xmlInputSource(&xml);
    if (!reader.parse(xmlInputSource)){
      postEvent(new QxtWebPageEvent(event->sessionID,
                             event->requestID,
                             DEFAULT_MESSAGE));
      return;
    }
    if (handler.method() == "ExistLogin"){
      QString bodyMessage = buildResponse(
                        this->checkLogin(handler.arg(0)),
                        "ExistLogin");
      postEvent(new QxtWebPageEvent(event->sessionID,
                            event->requestID,
                            bodyMessage.toUtf8()));
    }
    if (handler.method() == "CreateUser"){
      QString bodyMessage = buildResponse(
               this->createUser(handler.arg(0),
                                            handler.arg(1)),
               "CreateUser");
      postEvent(new QxtWebPageEvent(event->sessionID,
                                event->requestID,
                                bodyMessage.toUtf8()));
    }
  } else if (event->method.compare("GET")==0) {
    postEvent(new QxtWebPageEvent(event->sessionID,
                                event->requestID,
                                DEFAULT_MESSAGE));
   }
}

Após executar o parse no XML enviado pelo cliente, é selecionado o metodo invocado pelo cliente (ExistLogin ou CreateUser) e os parâmetros de cada um deles sendo chamada a função para executar a ação no servidor (acessar um banco de dados nesse caso) e é construida um mensagem (outro XML) contendo a resposta da ação (a função buildResponse() não foi alterada, ela já era poderosa suficiente!)

O restante da função é para impedir o metodo GET e que o XML contenha algum erro.

A facilidade em criar esse web service está no fato de bibliotecas como QtSOAP e QxT (Qt ExTended) permitir criar um cliente com meia duzia de linhas sem perder a força. Caso eu venha a utilizar esse web service para a aplicação do S60 eu faço um novo post.

Ah! os códigos para quem não pegou é http://github.com/wiglot/WebService e não deixem de visitar as outras páginas:

http://efforts.embedded.ufcg.edu.br/qt/

http://qt.nokia.com/products/appdev/add-on-products/catalog/4/Utilities/qtsoap

http://www.libqxt.org/

Abraços

De volta… e trago boas novas

De volta da terra dos programadores exilados :p

Nada como terminar e entregar um programa… Esse ano estive bastante (totalmente) envolvido no desenvolvimento da aplicação da minha IC (vou fazer um post disso mas adianto que é um sistema de representação de redes de distribuição de energia)… ahh o grupo que participo é esse.

Esse ano passamos por uma mudança gigante. Até Janeiro estavamos desenvolvendo o ASE (a ‘tar’ da aplicação que falei) usando C++ (velocidade, abstração, código legado, escolha pessoal) e GTK+ para interface, mas estavamos ‘apanhando’… e muito.

Cara, meses pra desenvolver o desenho de uma rede e grandes calculos pra fazer  a seleção (pega o ponto do click do mouse, verifica a distância dele até o segmento de reta da aresta do grafo… my head hurts….). Claro que faltava muito conhecimento de como é uma aplicação gráfica, como funciona a biblioteca GTK+, mas era muito laço. Quase 5 meses pra criar uma janelinha só pra desenhar a rede… acho que faltou ver alguns exemplos de representação de grafos com GTK+.

Então vi uma noticia no Br-Linux: Qt será licenciado sobre LGPL. Lembrei de ouvir muitas discuções que GTK+ é melhor, Qt é melhor, decidi conhecer esse tal de Qt… Foi amor a primeira lida….

Conversei com meu orientador sobre a troca de biblioteca gráfica. Depois de um breve brainstrom (ou Tormenta de idéias) decidi testar esse tal de Qt.  Baixa biblioteca, compila, estuda exemplos, cara tem um exemplo que parece o que eu quero, pega exemplo, altera um pouco, junta uns códigos e PRONTO cerca de uma semana  e meia e tinha algo muito semelhante ao que levamos 5 meses pra fazer, somando zoom, pan, seleção e movimentação dos itens. Cai nas graças do Qt 🙂

Em breve mais noticias.

P.S.  nada contra GTK+, acho que também faltou mais estudo de nossa parte…

Apresentação SIPE

É ainda to Vivo…. sei q a coisa aqui tah bem morta… mas to meio-completamente-totalmente sem tempo de tah escrevendo…

To de volta pra colocar o video da minha apresentação no SIPE da Unipampa