May 27
Articulos programación Puedes encontrar la primera parte del artículo aquí: Extendiendo PHP (I)

En esta segunda parte incluiremos el código necesario para que nuestra función haga su trabajo. Invertir una cadena o devolverla tal y como le ha llegado.

Una implementación en C para invertir una cadena podría ser esta (el código se presenta así con el proposito de ser claro, no óptimo)


#include
#include

char* reverseString(const char* str)
{
char* buffer;
int i=0;
buffer = (char*)malloc(strlen(str)*sizeof(char));
while(str[i]) buffer[strlen(str)-i++-1] = str[i];
return buffer;
}

int main(int argc,char** argv)
{
char* rstr;
rstr = (char*)reverseString("Hola mundo");
printf("%s\n",rstr);
free(rstr);
return(0);
}


Pues bien, habíamos dejado nuestra extensión en el directorio ext/dummy/ en donde podemos encontrar varios ficheros

config.m4 - reglas de configuración para \*nix
config.w32 - reglas de configuración para Güindow$
CREDITS - para meter el nombre de la extensión y tu nombre
EXPERIMENTAL - indica que la extensión es experimental
dummy.c - el código fuente de tu extensión
dummy.php - código de pruebas para tu extensión
Makefile.in - plantilla para el makefile
php_dummy.h - Cabecera para tu extensión
test/ - Directorio con las pruebas de regresión

Pasemos a editar dummy.c. Aunque esté lleno de código y marcaciones que pueden resultar extraños sólo debemos fijarnos en la estructura zend_module_entry llamada dummy_module_entry. Debemos sustituir PHP_RINIT(dummy) y PHP_RSHUTDOWN(dummy) por NULL pues no son necesarias para nuestra extensión. Se trata de código para inicializar o finalizar peticiones a la extensión. El código de la estructura se debe parecer a:


zend_module_entry dummy_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"dummy",
dummy_functions,
PHP_MINIT(dummy),
PHP_MSHUTDOWN(dummy),
NULL, /* Replace with NULL if there's nothing to do at request start */
NULL, /* Replace with NULL if there's nothing to do at request end */
PHP_MINFO(dummy),
#if ZEND_MODULE_API_NO >= 20010901
"0.1", /* Replace with version number for your extension */
#endif
STANDARD_MODULE_PROPERTIES
};


A continuación aparece comentado código para emplear valores propios de la extensión en las entradas de php.ini. Lo dejaremos como está, comentado, pues no las necesitaremos. Más abajo aparecen las implementaciones de MINIT(), MSHUTDOWN(), RINIT(), RSHUTDOWN() y MINFO(). Para MINIT() y MSHUTDOWN() sólo añadimos el código return SUCCESS; pues no queremos que hagan nada más. RINIT() y RSHUTDOWN() pueden ser borradas pero recuerda borrarlas también en el archivo de cabecera php_dummy.h

La función MINFO() se llama en la llamada a phpinfo() y en ella puedes añadir cualquier información que consideres relevante para la extensión.

Finalmente tenemos la función principal PHP_FUNCTION(dummy) donde agregaremos nuestro código adaptado:


/* {{{ proto string dummy(string msg, bool inv)
Devuelve la misma cadena enviada en orden normal o invertido */
PHP_FUNCTION(dummy)
{
char *msg = NULL;
int argc = ZEND_NUM_ARGS();
int msg_len;
zend_bool inv;
char *buffer = NULL;
int i=0;

if (zend_parse_parameters(argc TSRMLS_CC, "sb", &msg, &msg_len, &inv) == FAILURE)
return;

if(!inv) RETURN_STRINGL(msg, msg_len, 1);
buffer = (char*)malloc(strlen(msg)*sizeof(char));
while(msg[i]) buffer[strlen(msg)-i++-1] = msg[i];
RETURN_STRINGL(buffer, strlen(buffer), 1);
// php_error(E_WARNING, "dummy: not yet implemented");
}
/* }}} */


Antes de construir nuestra extensión debemos editar config.m4 para indicar como el usuario especificará que el módulo debe ser compilado en PHP. Estas líneas, comentadas por defecto, hacen justamente esto:



PHP_ARG_ENABLE(dummy, whether to enable dummy support,
[ --enable-dummy Enable dummy support])



Ahora existen 2 opciones a la hora de construir la extensión puedes hacerlo completamente independiente (standalone) y tu extensión será un módulo compartido cuya compilación será más rápida pero que necesitará ser habilitad desde php.ini para su carga o compilarla directamente en PHP que lleva más tiempo.

Para el modo independiente (standalone) debes ejecutar en el directorio de tu extensión el script phpsize que generará unos ficheros para configurar y construir tu extensión independientemente de PHP.

Luego sólo debes ejecutar:

$ ./configure
$ make
# make install

La extensión generada debería llamarse dummy.so y deberías copiarla al directorio donde php busca sus extensiones externas. Ahora debes precargar tu extensión desde php.ini mediante


extension=dummy.so


O desde el código de php directamente como:


dl('dummy.so');


Para la compilación dentro de PHP debes ejecutar en la raiz del código de PHP5

$ ./buildconf

Esto añadirá la opción --enable-dummy al script ./configure. Para probarlo ejecuta

$ ./configure --help

Ahora puedes construir PHP con:

$ ./configure --enable-dummy --enable-mysql=/usr/ ...

También puedes usar --enable-dummy=shared para forzar la compilación como librería compartida

¡Ya puedes probar tu extensión en tus scripts php!

<?php
var_dump(dummy('hola mundo',true));
?>

Una última consideración sobre memoria

La asignación de memoria dinámica es la causa principal de las perdidas de memoria (memory leaks). PHP dispone de funciones propias para la gestión de memoria dinámica. Estas funciones son:

emalloc()
efree()
estrdup()
estrndup()
ecalloc()
erealloc()

Que funcionan exactamente igual que sus contrapartidas en C. Estas funciones son seguras para evitar perdidas de memoria. Así que nuestra extensión tiene que sustituir la llama a malloc por emalloc. También debe ejecutar un efree por cada zona de memoria asignada con emalloc.

Publicado por Abraham Covelo

May 18
Programación Bueno para los que le interese el tema y quieran probar por ellos mismos cual es el que mejor servicio le ofrece como acortadoras de url hay va una lista.¿Alguién conoce algunas más?:

- bit.ly
- cli.gs
- digg.com
- is.gd
- kl.am
- tinyurl.com
- 307.to
- adjix.com
- b23.ru
- bacn.me
- bloat.me
- budurl.com
- clipurl.us
- cort.as
- dwarfurl.com
- ff.im
- fff.to
- href.in
- idek.net
- korta.nu
- lin.cr
- ln-s.net
- loopt.us
- memurl.com
- merky.de
- moourl.com
- nanourl.se
- ow.ly
- peaurl.com
- ping.fm
- piurl.com
- plurl.me
- pnt.me
- poprl.com
- rde.me
- reallytinyurl.com
- redir.ec
- rubyurl.com
- http://short.ie/
- short.to
- http://smallr.com/
- http://sn.vc/
- http://snipr.com/
- http://snipurl.com/
- http://snurl.com/
- http://tiny.cc/
- http://togoto.us/
- tr.im
- tra.kz
- twurl.cc
- twurl.nl
- u.mavrev.com
- u.nu
- ur1.ca
- url.az
- url.ie
- urlx.ie
- w34.us
- xrl.us
- yep.it
- zi.ma
- zurl.ws
- chilp.it
- notlong.com
- qlnk.net

Publicado por Abraham Covelo

Abr 29
Articulos programación Aunque la inmensa mayoría de las necesidades que plantea la programación en PHP se pueden resolver directamente con este lenguaje podemos encontrarnos con alguna necesidad muy especifica que nos obligue a extender las capacidades de PHP bien para agregar una nueva funcionalidad o bien para obtener un mayor rendimiento en determinadas partes del código.

Cualquiera que sea al necesidad también puede ser resuelta a través de PHP, creando una extensión. Empleando las herramientas proporcionadas por los desarrolladores de PHP y haciendo uso de su API en C podemos obtener lo que nos propongamos.

Existen dos tipos de extensiones: extensiones PHP y extensiones Zend. Las primeras proporcionan funciones o clases adicionales para el lenguaje (por ejemplo: GD, Ming etc) y las segundas son extensiones de bajo nivel que modifican el núcleo del lenguaje, como por ejemplo en los sistemas se cache por códigos de operación (APC, XCache, etc).

Para desarrollar una extensión en PHP necesitas una copia de código fuente de PHP y las herramientas de desarrollo para la programación en C. Lo primero lo puedes conseguir en www.php.net y lo segundo puede llegar en principio con gcc y gdb, compilador y depurador de GNU.

Otras herramientas necesarias, que tal vez ya tenga instalado tu sistema es

autoconf: 2.13
automake: 1.4+
libtool: 1.4.x+ (except 1.4.2)
bison: 1.28, 1.35, 1.75, 2.0 or higher
flex: 2.5.4 (not higher)
re2c: 0.9.11+ (0.12.0+ for HEAD)

Puedes emplear "apt-get install" para instalar todos estos paquetes si empleas distribuciones tipo debian.

Si no cumples casi ninguna de estos requerimientos te recomiendo que instales linux en tu máquina o cualquier otro sistema tipo UNIX. Y si no tienes ni la más remota idea de lo que estamos hablando deja de leer y sigue bajándote torrents de tus mp3s favoritos.

En el momento de escribir este artículo la última versión estable de PHP era la 5.2.9, quizás cuando leas estas líneas te parezca una versión anticuada pero esta noche es lo más reciente de PHP. Por supuesto la mejor forma de obtener el código más actualizado (y menos probado) es a través del repositorio público de PHP en http://cvs.php.net/.

Una vez que tengas el código de PHP lo mejor es que te familiarices mínimamente con su estructura y documentación. Lo segundo es preparar PHP en línea de comandos (CLI) para poder probar y depurar tu código rápidamente. Entra en el directorio de fuentes y ejecuta:

$ ./configure
$ make
# make install (como root)

Esto creará un binario ejecutable de php en /usr/local/bin. Si quieres tener disponible alguna extensión en este binario debes especificarlo al ejecutar configura pasándole la extensión que quieres tener como parámetro adicional; por ejemplo: --with-mysql=/usr --with-psgl --with-zlib para habilitar soporte para mysql, postgreSQL y zlib en el binario.

puedes verificar que todo ha ido bien ejecutando

$ php -v

Para generar el esqueleto de nuestra extensión debemos crear un fichero .def que defina la función que queremos agregar a nuestro php. Para continuar definamos la función que llamaremos dummy y que tendrá esta firma

string dummy(string $message,bool $inversion);

La función devolverá el mismo mensaje que se le envía como primer parámetro si el segundo parámetro es false y retornará la cadena invertida, con los caracteres en orden opuesto, si el segundo parámetro es true.

Nuestro fichero dummy.def podría contener lo siguiente

string dummy(string msg, bool invert) Devuelve la misma cadena enviada en orden normal o invertido

para generar el esqueleto de esta extensión debemos ejecutar lo siguiente si nos encontramos en la raíz del código fuente de php descargado

$ cd ext
$ vi dummy.def
(editamos el contenido del fichero)
$ ./ext_skel --extname=dummy --proto=dummy.def

El comando habrá creado un directorio dummy dentro de ext con los ficheros iniciales básicos para el funcionamiento de tu extensión, también te aparecerá un pequeño conjunto de instrucciones para compilar el código de tu extensión junto con php. Sin embargo ejecuta paso por paso estas instrucciones y ya tendrás tu primera extensión creada

$ cd .. (o ir a la raíz del código fuente de php descargado)
$ ./buildconf --force
$ ./configure --with-dummy
$ make

Para probarlo puedes ejecutar

$ ./sapi/cli/php -f ext/dummy/dummy.php

En la siguiente entrega entraremos en detalle de lo que acabamos de hacer y crearemos el código real para nuestra aplicación.

Ah! felicidades por haber creado tu primera extensión para PHP ;-)

Puedes ver la segunda parte de este artículo aquí: Extendiendo PHP (II)

Publicado por Abraham Covelo

Abr 26
Articulos programación Continuaremos con otro artículo sobre el gestor de versiones git. Esta vez nos centraremos en el trabajo colaborativo con git. Como crear nuestro repositorio a partir del creado por otras personas. Recordemos que git no utiliza un repositorio centralizado sino que cada desarrollador tiene un repositorio completamente funcional.

Lo primero es obtener un repositorio de otro desarrollador en una máquina local. Para ello basta ejecutar con dirigirnos al directorio donde queramos nuestro nuevo repositorio y a continuación ejecutar

$ git clone /ruta/al/repositorio directorio-nuevo-repositorio

ejemplo

$ git clone /home/novanebula/repo1 repo2

Suponiendo que /home/novanebula/repo1 contuviera el repositorio antiguo git crearía un nuevo directorio llamado repo2 que contiene el nuevo repositorio.

Podemos trabajar con normalidad sobre el nuevo repositorio. Cuando terminemos y estemos satisfechos con los cambios ejecutamos

$ git commit -a

Para llevar estos cambios al repositorio original debemos ir a ese repositorio o solicitar a la persona que lo lleve que ejecute desde el directorio de este repositorio:

$ git pull /ruta/nuevo/repositorio branch

ejemplo

$ git pull /home/novanebula/repo2 master

Y las modificaciones en el segundo repositorio se aplicarán al primero. Si este contenía modificaciones locales hay que resolver conflictos. Por lo tanto pull hace dos tareas trae las modificaciones de otro repositorio y mezcla estas modificaciones en el repositorio donde se ha ejecutado.

Si el usuario del primer repositorio quiere analizar las modificaciones que se han introducido en el segundo antes de ejecutar un pull. Puede hacerlo ejecutando

$ git fetch /home/novanebula/repo2 master
$ git log -p HEAD..FETCH_HEAD

Es posible definir dentro de un repositorio otros repositorios locales para simplificar las ordenes entre ellos:

(repo1)$ git remote add /home/novanebula/repo2 repo2

Ahora para recoger los cambios en el repo2 podemos ejecutar

(repo1)$ git fetch repo2

Analizar los cambios

(repo1)$ git log -p HEAD..FECH_HEAD

y mezclarlos en el repositorio actual con:

(repo1)$ git merge repo2/master

o con

(repo1)$ git pull . remotes/repo2/master

Además desde repo2 se puede mantener una copia actualizada de las modificaciones en repo1simplemente ejecutando

(repo2)$ git pull

Esta opción ya estaba disponible desde que repo2 fuera creado con el comando clone

(repo2)$ git config --get remote.origin.url

Git también mantiene una copia del repo original bajo el nombre origin/master:

(repo2)$ git branch -r

Si repo2 tuviera que trabajar desde otro servidor podría hacerlo a través del protocolo ssh ejecutando este clone:

$ git clone host-address:/home/novanebula/repo1 repo2

Git también tiene un protocolo nativo o puede usar rsync o http. Pudiendo trabajar incluso al estilo de CVS con un repositorio central sobre el que todos los desarrolladores enviasen sus cambios.

Publicado por Abraham Covelo

(Página 3 de 13, en total 49 entradas)