ST(0)
denota al primero,
ST(1)
al segundo, etc. Esto es: ST(i)
es equivalente a $_[$i]
.
El siguiente ejemplo provee una función sum
que devuelve
la suma de sus argumentos. Creamos la estructura de
ficheros y directorios con h2xs -A -n Sum
.
Después de añadir el directorio script
y el programa de
prueba usesum.pl
la estructura queda como sigue:
lhp@nereida:~/Lperl/src/XSUB/Sum$ tree . |-- Changes |-- MANIFEST |-- Makefile.PL |-- README |-- Sum.xs |-- lib | `-- Sum.pm |-- ppport.h |-- script | `-- usesum.pl `-- t `-- Sum.t
El programa de prueba ilustra el modo de uso:
lhp@nereida:~/Lperl/src/XSUB/Sum/script$ cat -n usesum.pl 1 #!/usr/bin/perl -w 2 use strict; 3 use blib; 4 use Sum; 5 6 die "Supply numbers\n" unless @ARGV; 7 my $s = sum(@ARGV); 8 print "$s\n";En la ejecución que sigue nótese el control de tipos cuando la entrada es ilegal:
lhp@nereida:~/Lperl/src/XSUB/Sum/script$ usesum.pl 2 3 5 10 lhp@nereida:~/Lperl/src/XSUB/Sum/script$ usesum.pl 2 3 a 4 Argument "a" isn't numeric in subroutine entry at ./usesum.pl line 7. 9 lhp@nereida:~/Lperl/src/XSUB/Sum/script$ usesum.pl 2.5 3.4 2.1 8 lhp@nereida:~/Lperl/src/XSUB/Sum/script$
A continuación pasamos a comentar los contenidos de Sum.xs
:
lhp@nereida:~/Lperl/src/XSUB/Sum$ cat -n Sum.xs 1 #include "EXTERN.h" 2 #include "perl.h" 3 #include "XSUB.h" 4 5 #include "ppport.h" 6 7 8 #ifdef SVf_IVisUV 9 # define slu_sv_value(sv) \ (SvIOK(sv)) ? \ (SvIOK_UV(sv)) ? (NV)(SvUVX(sv)) : (NV)(SvIVX(sv))\ : (SvNV(sv)) 10 #else 11 # define slu_sv_value(sv) (SvIOK(sv)) ? (NV)(SvIVX(sv)) : (SvNV(sv)) 12 #endif 13 14 15 MODULE = Sum PACKAGE = Sum 16 17 NV 18 sum(...) 19 PROTOTYPE: @ 20 CODE: 21 { 22 SV *sv; 23 int index; 24 if(!items) { 25 XSRETURN_UNDEF; 26 } 27 sv = ST(0); 28 RETVAL = slu_sv_value(sv); 29 for(index = 1 ; index < items ; index++) { 30 sv = ST(index); 31 RETVAL += slu_sv_value(sv); 32 } 33 } 34 OUTPUT: 35 RETVAL
sum
(línea 17).
Otros tipos posibles son: IV
por Integer Value,
PV
para las cadenas (Pointer Value).
xsubpp
que debe generar
un prototipo para la interface Perl a la subrutina.
sv
como puntero a un tipo escalar SV
(por
Scalar Value). El tipo SV es el tipo C usado por Perl para representar
las variables Perl de tipo escalar.
Analogamente los tipos AV y HV son las representaciones C de
los tipos Perl Array Value y Hash Value.
@_
.
return undef
.
ST(0)
es el primero,
ST(1)
el segundo, etc. Esto es: ST(i)
es equivalente a $_[$i]
.
RETVAL
casa con el tipo de retorno declarado para la función.
Por defecto la función C generada usará RETVAL
para guardar el
valor de retorno. En los casos sencillos el valor de RETVAL
será colocado en ST(0)
para que sea recibido por Perl como
el valor retornado por la XSUB.
Sin embargo, cuando hay una sección CODE:
como en este ejemplo,
el valor en RETVAL
no es devuelto automáticamente y es necesario
explicitarlo en una sección OUTPUT:
.
xsubpp
la XSUB sum
es traducida asi:
lhp@nereida:~/Lperl/src/XSUB/Sum$ sed -ne '27,51p' Sum.c XS(XS_Sum_sum) { dXSARGS; { NV RETVAL; dXSTARG; #line 21 "Sum.xs" { SV *sv; int index; if(!items) { XSRETURN_UNDEF; } sv = ST(0); RETVAL = slu_sv_value(sv); for(index = 1 ; index < items ; index++) { sv = ST(index); RETVAL += slu_sv_value(sv); } } #line 48 "Sum.c" XSprePUSH; PUSHn((NV)RETVAL); } XSRETURN(1); }
Casiano Rodríguez León