December 31st, 2008 by Jorge Machin
Para mí, una de las razones para considerar seriamente a boost en cualquier proyecto en C++ es el uso de los functores que le da. Realmente facilita mucho la creación de funciones "callback" y no causa 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;
}
Posteado en C/C++, Snapshots | 2 Comentarios »
December 1st, 2008 by Jorge Machin
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>
A continuación el programa de ejemplo 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, childi_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;
}
El cual compilamos con:
g++ -o main main.cpp -ltinyxml
Posteado en C/C++, Snapshots | No hay comentarios »
November 12th, 2008 by Jorge Machin
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 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.
Posteado en C/C++, Snapshots | No hay comentarios »
September 26th, 2008 by Jorge Machin
Una clase "quick and dirty" para crear hilos en cajas windows.
Encabezado:
#pragma once
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 );
}
Posteado en C/C++, Programación, Snapshots, Windows | No hay comentarios »
September 25th, 2008 by Jorge Machin
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();
curl_easy_setopt( curl, CURLOPT_URL, URL.c_str() );
curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, &URLImage::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;
}
Posteado en C/C++, Programación, Snapshots | No hay comentarios »