¿Cómo puedo pasar la matriz Perl por referencia al módulo C XS?¿Cómo puedo pasar una matriz a una función C en Perl XS?
my @array = (1..20);
XSTEST::test_array_passing(\@array);
¿Qué hago en XS por lo que ve la matriz?
¿Cómo puedo pasar la matriz Perl por referencia al módulo C XS?¿Cómo puedo pasar una matriz a una función C en Perl XS?
my @array = (1..20);
XSTEST::test_array_passing(\@array);
¿Qué hago en XS por lo que ve la matriz?
XS puede recibir una referencia a ARRAY como AV*
o SV*
. Este último tendría que ser desreferenciado a AV*
.
use Inline C => DATA;
@array = (1 .. 20);
$r = sum_of_elements1(\@array);
$s = sum_of_elements2(\@array);
print "$r $s\n"; # produces output: "210 210\n"
__END__
__C__
double sum_of_elements1(AV* array)
{
int i;
double sum = 0.0;
for (i=0; i<=av_len(array); i++) {
SV** elem = av_fetch(array, i, 0);
if (elem != NULL)
sum += SvNV(*elem);
}
return sum;
}
double sum_of_elements2(SV* array_ref)
{
AV* array;
if (!SvROK(array_ref) || SvTYPE(SvRV(array_ref)) != SVt_PVAV)
croak("expected ARRAY ref");
array = (AV*) SvRV(array_ref);
return sum_of_elements1(array);
}
El archivo .xs producido por este código declara:
double
sum_of_elements1 (array_ref)
SV * array_ref
double
sum_of_elements2 (array)
AV * array
Editar: en sum_of_element2()
, agregó la comprobación de que el SV * era una referencia a un array.
No se puede pasar una matriz Perl y convertirla automágicamente, por ejemplo, en una matriz C de entradas. Tendrá que recurrir a XS y al perlapi para hacer esto. La razón es bastante simple: una matriz perl contiene escalares sin tipo. Una matriz C contiene N elementos del mismo tipo.
Lo que puedes hacer es tener un XSUB
que lleva un SV*
. SV
representa el valor escalar. Naturalmente, esto incluye referencias (RV
) y, por lo tanto, también referencias a matrices (AV
).
Así es como se puede comprobar si un determinado SV*
fuente es una referencia a un array:
SV* tmpSV;
AV* theArray;
if (SvROK(source)) { /* it's a reference */
tmpSV = (SV*)SvRV(source); /* deref */
if (SvTYPE(tmpSV) == SVt_PVAV) { /* it's an array reference */
theArray = (AV*)tmpSV;
/* do stuff with the array here */
}
}
Gracias por la respuesta, voy a intentar esto, pero en este caso tendrá que proporcionar operaciones en el archivo XS solo, no puedo poner mis operaciones de array en un archivo C separado, ya que necesitaré acceso a la estructura de datos AV/SV allí – Avinash
Avinash: puede poner el código que usa perlapi en archivos c arbitrarios. Solo incluya los encabezados de Perl necesarios. – tsee
También desea comprobar si la referencia es una referencia a una matriz. – tsee