lunes, 31 de octubre de 2011

Pasar arreglo de un archivo a otro de PHP con GET

Hola a todos. El día de hoy les traigo un "truco" que recientemente usé en una página web que hice para la universidad.

Es posible que tengamos la necesidad de pasar un arreglo completo de un archivo a otro de PHP y resulta muy incómodo pasar cada uno de sus componentes. Para esto, lo que haremos será serializar el arreglo con la función serialize de PHP, y la cadena resultante la codificaremos con urlencode para ser pasada a otro archivo. En el otro archivo solo tendremos que decodificar la cadena con la función urldecode y deserializarla con unserialize.

Archivo emisor:
arr['ind'] = 4;

$val = urlencode(serialize(arr));

header('Location: recptor.php?s=$var');


Archivo receptor:
$s = unserialize(urldecode(stripslashes($_GET['s'])));
echo $s['ind'];


Así el echo de la última linea nos mostrará "4".

viernes, 28 de octubre de 2011

Obtener ID luego de insertar un registro en SQL

Supongamos que tenemos la siguiente tabla en nuestra base de datos:

tabla
idEntero autoincrementable
campo1varchar(10)
campo2varchar(30)
campo3varchar(30)


El problema ocurre cuando hacemos una inserción en la base de datos y necesitamos saber cual fue el id con el que quedó nuestro registro.

La solución a este problema llega a nosotros gracias a la clausula RETURNING. Miremos como sería nuestra consulta:

INSERT INTO tabla (campo1, campo2, campo3) VALUES ('c1', 'c2', 'c3') RETURNING id;

La anterior consulta inserta el registro en la tabla tabla y retorna el id con el que queda este. Ahora si nuestra intensión es guardar este valor en una variable dentro de una función SQL podemos hacerlo así:


CREATE FUNCTION funcion (VARCHAR, VARCHAR, VARCHAR) RETURN INTEGER
AS$$
DECLARE
id_t INTEGER;
BEGIN
INSERT INTO tabla (campo1, campo2, campo3) VALUES ($1, $2, $3)
RETURNING id INTO id_t;
RETURN id_t;
END;
$$LANGUAGE plpgsql;

Función hecha en PostgreSQL


La clausula "RETURINIG id INTO id_t" podemos usarlo independiente del gestor de bases de datos que estemos usando.

martes, 20 de septiembre de 2011

Eliminar Wine completamente

Hola a todos. Si quieres eliminar Wine completamente de tu sistema Linux, usando solo los comandos de desinstalación no es suficiente. Veremos entonces lo necesarios para purgar completamente Wine:

$ aptitude purge wine
$ rm -rf $HOME/.wine
$ rm -f $HOME/.config/menus/applications-merged/wine*
$ rm -rf $HOME/.local/share/applications/wine
$ rm -f $HOME/.local/share/desktop-directories/wine*
$ rm -f $HOME/.local/share/icons/????_*.xpm

domingo, 11 de septiembre de 2011

Crear librerías dinámicas en C++ para Windows usando CMake

Primero, la diferencia entre librería dinámica y librería estática:

Las librerías estáticas quedan incluidas en el ejecutable, mientras las dinámicas son ficheros externos, con lo que el tamaño de la aplicación (nuestro ejecutable) es mayor en el primer caso que en el segundo. Esto puede ser de capital importancia en aplicaciones muy grandes, ya que el ejecutable debe ser cargado en memoria de una sola vez

Las librerías dinámicas son ficheros independientes que pueden ser invocados desde cualquier ejecutable, de modo que su funcionalidad puede ser compartida por varios ejecutables. Esto significa que solo se necesita una copia de cada fichero de librería (DLL) en el Sistema. Esta característica constituye la razón principal de su utilización, y es también origen de algunos inconvenientes, principalmente en sistemas como Windows en los que existen centenares de ellas.

Referencia: Tipos de librerías en C y C++


Construcción de una DLL

Cuando se construye un fuente que será compilado para producir una DLL, los objetos (funciones y clases) que deban ser accesibles desde otros ejecutables, se denominan exportables, también callbacks si son funciones, en atención a una denominación muy usual en la literatura inglesa ("callback functions"). Esta circunstancia debe ser conocida por el compilador, por lo que es necesario especificar qué recursos se declaran "exportables"; además debe instruirse al "linker" para que genere una librería dinámica en vez de un ejecutable normal.

En los compiladores para la plataforma Windows existen varias formas para declarar una función o recurso como exportable, pero aquí veremos uno de los más simples y directos, el especificador dllexport.


Especificador dllexport
Los recursos "exportables" pueden ser también declarados mediante el especificador __declspec(dllexport).

Sintaxis:
Existen dos formas:
__declspec(dllexport) valor-devuelto funcion (argumentos);
class __declspec(dllexport) nombre-de-clase;
__declspec(dllexport) tipo-de-dato nombre-de-variable;


Ejemplos
extern "C" __declspec(dllexport) double MayorValor(double, double);
class __declspec(dllexport) A { /* ... */ };
__declspec(dllexport) int x;

Referencia: Crear una librería dinámica


Ahora sí, a la acción. Supongamos que tenemos tres archivos, así:


ArchivoDescripción
ClaseA.hppCabecera de la clase "ClaseA"
ClaseA.cppArchivo fuente con la definición de la clase "ClaseA"
main.cppCódigo del ejecutable


Donde la ClaseA estará contenida en la librería que queremos crear. Miremos el código de cada una de los archivos:


ClaseA.hpp

#ifndef CLASEA_HPP
#define CLASEA_HPP

class __declspec(dllexport) ClaseA
{
public:
ClaseA(int iId = 0);

int id() const;
void id(const int &iId);

protected:
int _iId;
};

__declspec(dllexport) ClaseA * nuevaReferencia(int iId = 0);
__declspec(dllexport) void eliminarReferencia(ClaseA * pClaseA);

// Definición de métodos inline
inline int ClaseA::id() const
{
return _iId;
}

inline void ClaseA::id(const int &iId)
{
_iId = iId;
}

#endif



ClaseA.cpp

#include<ClaseA.hpp>

ClaseA::ClaseA(int iId)
{
_iId = iId;
}

ClaseA * nuevaReferencia(int iId)
{
return new ClaseA(iId);
}

void eliminarReferencia(ClaseA * pClaseA)
{
delete pClaseA;
}


main.cpp

#include<iostream>
#include<ClaseA.hpp>

using std::cout;
using std::endl;

int main(int argc, char **argv)
{
cout << "Ejemplo de creación de librerías dinámicas" << endl;

ClaseA * pClaseA = nuevaReferencia();

cout << "id:\t" << pClaseA->id() << endl;

pClaseA->id(3);

cout << "id:\t" << pClaseA->id() << endl;

eliminarReferencia(pClaseA);

return 0;
}



Tenemos una clase llamada ClaseA que estará contenida en nuestra librería. Y un archivo main.cpp que contiene el código de nuestro ejecutable.

Ahora creamos el archivo de configuración de CMake:

CMakeLists.txt

project(libreria)
cmake_minimum_required(VERSION 2.8)

include_directories( ${CMAKE_BINARY_DIR} . )

add_library(Core SHARED
ClaseA.hpp
ClaseA.cpp
)

add_executable(main main.cpp)

target_link_libraries(main Core)



Creamos una librería dinamica (SHARED) llamada Core, y un ejecutable llamado main.

Miremos que no es necesario declarar como exportables los métodos y miembros de la clase, ya que la clase es exportable.

En el momento de construcción de la librería ciertos identificadores deben ser declarados dllexport. Pero para poder usar esta en la construcción de otras librerías o ejecutables es necesario importarlos. Para esto usamos el especificador dllimport. Para esto es necesario que en el momento de construcción el especificador dllexport sea cambiado por dllimport. Para automatizar esto, usaremos un cuarto archivo LibExport.hpp:

LibExport.hpp

#ifndef LIBEXPORT_HPP
#define LIBEXPORT_HPP

#ifdef _WIN32
# ifdef Core_EXPORTS
# define EXPORT __declspec( dllexport )
# else
# define EXPORT __declspec( dllimport )
# endif
#else
# define EXPORT
#endif

#endif




En el momento en que se está construyendo la librería, CMake define un macro llamado <nombre de la librería>_EXPORTS. Lo que hacemos es aprovechar esto y decir, que cuando se esté construyendo la librería, EXPORT adquiera el valor de __declspec( dllexport ), de lo contrario tendrá el valor de __declspec( dllimport ) (siempre y cuando el sistema operativo sea Windows). Luego de esto, modificamos ClaseA.hpp para que soporte tanto dllexport como dllimport:

ClaseA.hpp


#ifndef CLASEA_HPP
#define CLASEA_HPP

#include<libexport.hpp>


class EXPORT ClaseA
{
public:
ClaseA(int iId = 0);

int id() const;
void id(const int &iId);

protected:
int _iId;
};

EXPORT ClaseA * nuevaReferencia(int iId = 0);
EXPORT void eliminarReferencia(ClaseA * pClaseA);

// Definición de métodos inline
inline int ClaseA::id() const
{
return _iId;
}

inline void ClaseA::id(const int &iId)
{
_iId = iId;
}

#endif



Cuando compilamos el proyecto, podemos ver que se crean tres archivos; main.exe, Core.dll, Core.obj. Esta ultima una librería estática clásica que sirve como índice o diccionario de la dinámica.

lunes, 23 de agosto de 2010

Argumentos desde la linea de comandos C/C++

En este post vamos a ver como reconocer los argumentos que recibe nuestro programa desde la linea de comandos cuando es ejecutado.

Cuando declaramos correctamente la función main, lo hacemos de la siguiente forma:

int main(int argc, char **argv)

Podemos observar que la función main recibe dos parámetros (argc, argv). Donde:

-argv: Es un array de cstrings, que contiene los parámetros pasados por la linea de comandos. En la primera posición del array, podemos encontrar la orden con la cual fue ejecutado nuestro programa.
A partir de la segunda posición están los argumentos que hemos recibido.

-argc: Es un número entero, que nos indica la cantidad de parámetros recibidos (el tamaño del array argv).

Observemos el siguiente código:


#include<iostream>

using namespace std;

int main(int argc, char **argv)
{
cout << "cantidad de argumentos: " << argc-1 << endl;
cout << "orden de ejecución: " << argv[0] << endl;
for(int i = 1; i < argc; i++)
{
cout << "Posición nro " << i
<< ": " << argv[i] << endl;
}
return 0;
}


El siguiente ejemplo esta probado en GNU/Linux.

Si ejecutáramos el código anterior desde una terminal, de la siguiente forma:

./argumentos argumento1 argumento2


Obtemdremos la siguiente salida:

cantidad de argumentos: 2
orden de ejecución: ./argumentos
Posición nro 1: argumento1
Posición nro 2: argumento2


Miremos entonces, que después de ejecutar el programa, podemos enviar la cantidad de parámetros que deseemos, siempre y cuando separemos cada uno de estos con un espacio.

miércoles, 21 de abril de 2010

Factorial en C++

Un problema muy frecuente cuando estamos dando nuestros primeros pasos en la programación, es la realización de un algoritmo para encontrar el factorial de un número dado (simbolizado como n!). Para solucionar este problema, el día de hoy les traigo dos soluciones realizadas por mi. Pero primero, ¿qué es el factorial de un número?


"Para todo número natural n, se llama n factorial o factorial de n al producto de todos los naturales desde 1 hasta n"
Fuente: Wikipedia


El prototipo de la función factorial que use para las dos soluciones es:

//Prototipo de la función factorial
long int factorial(unsigned int numero);

En el primer algoritmo nos valemos de un ciclo, en el cual acumularemos el resultado de todas las multiplicaciones desde uno (1) hasta llegar a n, dando fin al bucle, y entregando el resultado:

//Factorial usando ciclos
long int factorial(unsigned int numero)
{
long int lFact = 1L;
for(int i = 2; i <= numero; i++)
lFact *= i;
return lFact;
}

En el segundo algoritmo, tomamos como base las características que tiene la función factorial, y hacemos un procedimiento recursivo hasta encontrar el factorial requerido:

//Factorial usando recursión
long int factorial(unsigned int numero)
{
if(numero == 0U || numero == 1U)
return 1L;
return numero * factorial(numero - 1U);
}

lunes, 19 de abril de 2010

Pasar matrices por referencia en C++

Cuando declaramos un array de algún tipo, en realidad estamos declarando un puntero a la dirección de memoria del primer elemento del array. Y cuando accedemos a los subíndices del array por medio del operador [], estamos haciendo uso de la aritmética de punteros para movernos por la memoria accediendo a las direcciones que necesitamos. Podemos ver esto de una forma mas fácil en el siguiente ejemplo:


//Primero declaramos un array de enteros
//de dimensión diez (10)

int array[10];

//Luego creamos un puntero a un entero
int * pArray;

//y asignamos la dirección del array al puntero
pArray = array;


Note se que cuando asignamos la dirección lo hacemos directamente, sin necesidad de usar el operador & (dirección de). Esto pasa, porque en realidad 'array' es un puntero como 'pArray'.

Ahora si queremos acceder a los subíndices, podemos hacerlo por medio de 'pArray' y de 'array'. Miremos el siguiente ejemplo:

//En este ejemplo estamos inicializando
//los diez elementos de 'array' en cero

for(int i = 0; i < 10; i++)
{
pArray[i] = 0;
}

Ahora lo importante. ¿Cómo pasar arreglos por referencia en C++? Como ya vimos, en realidad los arreglos son punteros al primer subíndice de un array. Entonces para pasar un array por referencia, resulta ser sencillo. Observemos el siguiente prototipo:

void inicializar(int filas, int columnas,
int matriz[filas][columnas]);

Lo que hacemos aquí es, primero pasar las dimensiones de la matriz, y luego la declaramos. El orden aquí es importante, ya que si declaramos el array sin conocer sus dimensiones, el compilador arrojara un error, pues no sabrá como tiene que dimensionar el arreglo. Ahora, para llamar la función simplemente hacemos lo siguiente:

//llamada a la función 'inicializar'
inicializar(filas, columnas, matriz);

donde 'matriz' es una matriz de dimenciones [filas][columnas].