From the category archives:

Snapshots

Functores a la boost

by Jorge Machin on December 31, 2008 · 2 comments

in C/C++, Snapshots

Para mí, una de las razones para considerar seriamente a boost en cualquier proyecto en C++ es su implementación de functores. Realmente facilita mucho la creación de funciones "callback" y "delegates" sin causar mucha penalización en el rendimiento de un programa.

¿Porqué facilita el trabajo si los callbacks bien se pueden hacer con tan solo un apuntador a función? La respuesta es fácil si estas trabajando con un enfoque orientado a objetos. Para usar un apuntador a una función miembro, esta necesita ser estática o ser llamada con ayuda de su objeto. Las dos cosas bastante engorrosas.

Veamos como se sortea estos inconvenientes usando boost:

#include <iostream>

#include <boost/function.hpp>
#include <boost/bind.hpp>

using namespace std;

class Callback {

  public:

     void set_callback_function( boost::function<void()> function ) {

       this->callback_function = function;

     }

     void execute_callback_function() {

       if(  !callback_function.empty() )

          callback_function();

     }

  private:

     boost::function<void ()> callback_function;

};

class MiClase {

  public:

     void funcion() {

        cout <<"¡iujú! ¡Si se llamó!" <<endl;

     }

};

int main() {

  Callback callback;

  MiClase miclase;

  callback.set_callback_function( boost::bind( &MiClase::funcion, &miclase ) );

  callback.execute_callback_function();

  return EXIT_SUCCESS;

}

Probando el código en línea

En la siguiente URL, puedes probar este programa en línea: http://www.ideone.com/hbMXbtFR

{ 2 comments }

La biblioteca TinyXML es muy liviana y permite parsear rapidamente XMLs sin tener que hacer mucho formalismo. En este post presento un código de ejemplo:

El xml que queremos parsear como ejemplo es el siguiente:

<?xml version="1.0">

<ELEMENT attribute="attribute">
   <CHILD>child</CHILD>
</ELEMENT>

Lo grabamos con el nombre ejemplo.xml.

A continuación el programa en c++ que realiza el parseo:

#include <iostream>

#include "tinyxml.h"

using namespace std;

int main() {

  TiXmlDocument doc;

  if ( !doc.LoadFile( "ejemplo.xml" ) )  {

    cout <<"Error: Can't load file ejemplo.xml" << endl;
    return EXIT_FAILURE;

  }

  string attribute, child_value;

  TiXmlElement *element;

  element = doc.FirstChildElement( "ELEMENT" );

  if ( element->Attribute( "attribute" ) != NULL )

      attribute = string ( element->Attribute( "attribute" ) );

  cout <<"attribute: " <<attribute <<endl;

  TiXmlElement* child = element->FirstChildElement("CHILD");

  if ( child != NULL )

    child_value = string( ( ( child->FirstChild() )->ToText() )->Value() );

  cout <<"child value: " <<child_value <<endl;

  return EXIT_SUCCESS;

}

Lo grabamos como main.cpp y lo compilamos con:

g++ -o main main.cpp -ltinyxml

{ 8 comments }

SnapShoot: Hilos en C++ a la boost

by Jorge Machin on November 12, 2008 · 1 comment

in C/C++, Snapshots

Boost es una excelente librería con todo lo que un buen programador de C++ pudiera necesitar. Además está desarrollada para hacer la programación sencilla, elegante y rápida. A continuación incluyo un ejemplo simple de una clase que encapsula el manejo de hilos usando Boost y que puede servir de prototipo en diversos proyectos:

#include <iostream>

#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>

class Hilo {

   public:

      Hilo() : keepgoing( true ), thread( boost::bind( &Hilo::do_work, this ) ) { };

      ~Hilo() {

         keepgoing = false;

         // Necesitamos esperar a que el hilo se acabe :)

         thread.join();

      }

   private:

      bool keepgoing;

      boost::thread thread;

      void do_work() {

          // Aquí es donde se lleva a cabo toda la acción.

          while( keepgoing ) {

             std::cout <<"Hilo" << std::endl;
             sleep(1);

          }

       }

};

int main( void ) {

   Hilo *hilo = new Hilo();

   sleep(20);

   delete hilo;

   return EXIT_SUCCESS;

}

El programa lo podemos compilar con:

g++ -O2 -o main main.cpp -lboost_thread-mt

Notas:

- Como se puede ver esta aproximación es más parecida a como le hace C# que Java.

- El hilo comienza al crearse el objeto.

- No hay manera de controlar manualmente el tamaño del stack

- Si no hay recursos suficientes se lanza una excepción y el objeto no se crea.

{ 1 comment }

Snapshot: Hilos en C++ (Windows)

by Jorge Machin on September 26, 2008 · 0 comments

in C/C++, Programación, Snapshots, Windows

Una clase "quick and dirty" para crear hilos en cajas windows.

Encabezado:

#pragma once

#include <windows.h>

class CThread {

   public:

      // Constructor por defecto:

      CThread(void);

      // Destructor virtual
   
      virtual ~CThread(void);

      // Esta función inicia el hilo:

      bool start();

      // Esta función se debe sobrecargar con lo que tiene que hacer el hilo:

      virtual void run() = 0;

      // Esta función espera a que el hilo se detenga. Se debe llamar en el destructor de la clase derivada.

      void join();

   private:

      unsigned long id;

      void *threadHandle;

      static DWORD WINAPI entryPoint( void *pthis );

};

Archivo cpp:

#include "StdAfx.h"
#include "thread.h"

CThread::CThread(void) : threadHandle( NULL ) {

   MessageBox( NULL, "CThread::CThread", "Aviso", MB_OK );

}

DWORD WINAPI CThread::entryPoint( void *pthis ) {

   CThread *pt = ( CThread * ) pthis;
   pt -> run();
   return 0;

}

bool CThread::start() {

   threadHandle = CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) entryPoint, this, 0, &id );
   return true;

}

void CThread::join() {

   if ( threadHandle != NULL )

      WaitForSingleObject( threadHandle, INFINITE );

}

CThread::~CThread(void) {

   MessageBox( NULL, "CThread::~CThread", "Aviso", MB_OK );

   if ( threadHandle != NULL )   

      CloseHandle( threadHandle );

}

Como se dislumbra de los comentarios, para utilizarla es necesario crear una clase que herede de Cthrean y sobrecargar la función run con lo que debe hacer nuestro hilo.

{ 0 comments }

Snapshot: Obteniendo archivos HTTP en C++

by Jorge Machin on September 25, 2008 · 0 comments

in C/C++, Programación, Snapshots

Ya es común para un programador, no solamente el tener que leer archivos del disco duro local, sino también leerlos desde un sitio web; Ya sea un web service, una imagen o un XML. Afortunadamente la libreria libcurl resuelve el problema con muy pocas líneas de código.

En este post, pongo un pequeño ejemplo de como se usaría en C++ para pequeños programas de apoyo:

#include <string>
#include <iostream>

#include "curl/curl.h" 

class URLFile {

   public:

      std::string get( const std::string &URL ) {

         // Inicialización:

         CURL *curl = curl_easy_init();

         // URL a consultar

         curl_easy_setopt( curl, CURLOPT_URL, URL.c_str() );

         // Configuaración del callback

         curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, &URLFile::write_data);
         curl_easy_setopt( curl, CURLOPT_WRITEDATA, &data);

         // Obtén el archivo:
                       
         CURLcode result = curl_easy_perform(curl)

         // Al final hay que limpiar todo:

         curl_easy_cleanup(curl);

         if (result != CURLE_OK)  {

            return "";

         }

         return data;

      }

   private:
 
      // Variable que usamos para guardar el contenido del archivo:

      std::string data;

      // Callback que utiliza curl:

      static size_t write_data( char *buffer, size_t size, size_t nmemb, void *userp ) {

         int len = size * nmemb;
 
         if ( buffer != NULL ) 

            ( ( std::string * )  userp )->append( buffer, len )

         return len;

      }
 
};

int main() {

   URLFile file;

   std::string test = file.get( "www.machin.com.mx" );

   std::cout <<"Test:" <<std::endl <<test <<std::endl;

   return 0;

}

{ 0 comments }