Crear SVs a partir de punteros en C.

Alejandro Forero Cuervo bachue at bachue.com
Tue Nov 23 17:53:44 CST 1999


Saludos.

Tengo una librería de C que me ofrece la posibilidad de registrar
funciones de callback C. La idea es que el caller pase un apuntador
a su función y un apuntador a un objeto que será pasado a la función
como argumento. El prototipo de la función para registrar la rutina de
callback es el siguiente (realmente es muy diferente, pero no importa):

  int register(int (*funcion)(HBInfo *), void *object);

Eso hará que cuando llame ciertas funciones de la librería, esta llame
mis funciones de callback varias veces según lo que suceda.

Ahora bien, en mi archivo XS, donde creo la extensión que permita utilizar
la librería desde Perl, declaro la función register, de tal manera que
uno pueda hacer lo siguiente en Perl (realmente es muy diferente, pero
no importa):

  use alejo;
  alejo::register(\&function);

  sub function {
    print "I was called!\n";
  }

Notarán que por ahora no se puede pasar un objeto de uno en Perl
(mientras que en C hay un apuntador object donde uno pasa un dato que le
será pasado a la rutina de callback). Eso no es grave y será arreglado
en el futuro. Ignoremos el detalle, no es relevante.

En la función asociada a register de Perl, lo que hago es, básicamente,
lo siguiente (realmente es muy diferente, pero no importa):

int
nombre_de_funcion (perl_func)
    SV *perl_func;
    ALIAS:
        alejo::register = 1
    CODE:
        RETVAL = register(funcion_magica, perl_func);
    OUTPUT:
        RETVAL

Con eso lo que logro es que cuando la librería de C necesite llamar el
callback, llame funcion_magica y le pase el SV de la rutina (el parametro
perl_func), para que funcion_magica se encarge de llamarla.

Ahora bien, como se puede ver en el prototipo de la función register
de C, funcion_magica tiene el siguiente prototipo y está declarada al
comienzo de mi archivo XS:

  int funcion_magica (Info *data);

El tipo Info contiene, principalmente (desde el punto de vista del
usuario de la librería), una tabla de símbolos con punteros a diferentes
funciones que se pueden llamar dentro de funcion_magica (de la forma
data->sym->funcion(...)).

En la declaración de funcion_magica tengo que extraer de data el SV de
la rutina de Perl (que antes llamé perl_func, al registrar funcion_magica
como callback) para llamarlo. Tengo que llamarlo.

Y he aquí el problema. Al llamarlo, quiero pasarle a la rutina de Perl
como parametro ese mismo apuntador data, para que desde la rutina se
pueda jugar con esa información. Para esto, tengo que crear un SV con
el valor de data y decirle a Perl a que clase asociarlo.

Por ejemplo, en mi archivo XS declaro la clase Info y creo varios métodos
asociados a ella. Yo quiero que en el código de Perl de la rutina de
callback, las personas puedan hacer:

  my $var = shift;
  $var->addcontent("foo");
  $var->setvalue("bar");

En mi archivo XS declaro la clase Info y sus métodos, tales como
addcontent y setvalue (realmente son métodos muy diferentes, pero no
importa).

El problema es que en funcion_magica no tengo el SV para meter en el
stack de Perl.

Es decir, necesito una función que probablemente tenga el siguiente
prototipo:

  SV *sv_new_blah ( char *classname, void *value );

Esa función creará un SV de tipo classname cuyo valor será value, de
tal modo que cuando en la rutina de Perl lo saquen de la pila, puedan
hacerle las cosas que en mi XS defino que se pueden hacer en esa clase.

He estado mirando los manuales y lo más relevante que encontré fue la
función newSVrv:

  SV* newSVrv(SV* rv, char* classname);

El manual (perlguts) dice:
 
  /* Still under construction */

  Upgrades rv to reference if not already one.  Creates new
  SV for rv to point to.  If classname is non-null, the SV
  is blessed into the specified class.  SV is returned.

Sin embargo, me imagino que no puedo pasar cualquier apuntador como
rv simplemente haciendole un cast.

Dice `SV is returned'. Obviamente un SV es retornado, de acuerdo con el
prototipo. Es el mismo rv el que es retornado?

En fin, alguien con más experiencia (la primera vez que programé en Perl
fue hace menos de dos semanas) sabe como hacerlo?

Gracias.

Alejo.
http://bachue.com/alejo

Pd: La librería se llama HB y es un sistema bastante nuevo para construir
contenido en web de manera dinámica, extensible a través de módulos
cargados en tiempo de ejecución, jugando el mismo papel que Perl+CGI /
PHP / MetaHTML / ASP y similares. Pueden encontrar más información al
respecto en <http://bachue.com/hb>.

--
The mere formulation of a problem is far more essential than its solution.
      -- Albert Einstein.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 232 bytes
Desc: not available
Url : http://mail.pm.org/archives/bogota-pm/attachments/19991123/522ff1cd/attachment.bin


More information about the Bogota-pm mailing list