我该如何将Perl数组通过引用传递给C XS模块?
my @array = ( 1..20 );
XSTEST::test_array_passing(\@array);
在XS中,我应该怎么做才能看到这个数组?
XS 可以接收一个数组的引用作为 AV*
或 SV*
。后者需要被解除引用为 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);
}
这段代码产生的 .xs 文件声明了:double
sum_of_elements1 (array_ref)
SV * array_ref
double
sum_of_elements2 (array)
AV * array
编辑:在sum_of_element2()
中,添加了检查* SV是否是数组引用的代码。
SV*
的XSUB
。 SV
代表标量值。这自然包括引用(RV
),因此也包括对数组(AV
)的引用。SV*
源是否是对数组的引用: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 */
}
}
use strict;
和use warnings;
呢? - Chris LutztmpSV
必须是一个打字错误(因为它是未定义的变量),截至2017年,该行应该写成:if (! SvROK(array_ref) || SvTYPE(SvRV(array_ref)) != SVt_PVAV){
。虽然我不打算编辑你的答案。但这个答案确实帮助了我解决了一个相关的问题,所以我想评论一下我发现的内容。 - stevieb