perlxs-从c数组返回perl数组



使用XS,我试图将值从C数组传递到可以在脚本中使用的Perl数组中。

这是我的xs文件中的代码:

AV *
DoubleArray::getPerlArray()
CODE:
r = newAV();
for(size_t i=0; i < THIS->count; i++)
{
av_push(RETVAL,newSVnv(THIS->data[i]));
}
OUTPUT:
RETVAL

它编译得很好,但当我在perl中运行以下内容时:

my @d = $C->getPerlArray();
foreach(@d)
{
print "$_n";
}

当我期望它打印数字列表时,它只打印ARRAY(0x1408cdc)

如何修改代码以正确地传回perl数组?

Perl子只能返回(0个或更多)标量。当您试图返回一个数组时(如果不崩溃Perl,这是不可能的!),默认类型映射会返回对该数组的引用。

请注意,您的程序也会泄漏内存(因为AV*的默认类型映射应该将您的数组固定化,但没有)。


返回参考,方法1

AV* /* Returns: sv_2mortal(newRV(RETVAL)) */
DoubleArray::getPerlArrayRef()
PREINIT:
size_t i;
CODE:
RETVAL = (AV*)sv_2mortal((SV*)newAV());
for (i=0; i < THIS->count; ++i) {
av_push(RETVAL, newSVnv(THIS->data[i]));
}
OUTPUT:
RETVAL

内存泄漏检查:

  • 数组的refcnt:1(newAV)-1[延迟](sv_2mortal)+1(newRV)=1[delayed]
  • 参考文献参考文献:1(newRV)-1[延迟的](sv_2mortal)=0[延迟的]

Perl:

my $array = $C->getPerlArrayRef();
say for @$array;

返回参考,方法2

SV* /* Returns: sv_2mortal(RETVAL) */
DoubleArray::getPerlArrayRef()
PREINIT:
AV* av;
size_t i;
CODE:
av = newAV();
RETVAL = newRV_noinc((SV*)av);
for (i=0; i < THIS->count; ++i) {
av_push(av, newSVnv(THIS->data[i]));
}
OUTPUT:
RETVAL

内存泄漏检查:

  • 数组的refcnt:1(newAV)+0(newRV_noinc)=1(由引用所有)
  • 参考文献参考文献:1(newRV_noinc)-1[延迟的](sv_2mortal)=0[延迟的]

Perl:<同上>


返回参考,方法3

void
DoubleArray::getPerlArrayRef()
PREINIT:
AV* av;
size_t i;
PPCODE:
av = newAV();
mXPUSHs(newRV_noinc((SV*)av));
for (i=0; i < THIS->count; ++i) {
av_push(av, newSVnv(THIS->data[i]));
}

内存泄漏检查:

  • 数组的refcnt:1(newAV)+0(newRV_noinc)=1(由引用所有)
  • 参考文献参考文献:1(newRV_noinc)-1[延迟的](mXPUSHs)=0[延迟的]

Perl:<同上>


返回标量

我们必须检查上下文,因为我们不能在列表上下文之外的堆栈上放置多个标量。

void
DoubleArray::getElements()
PREINIT:
size_t i;
U8 gimme = GIMME_V;
PPCODE:
if (gimme == G_ARRAY) {
EXTEND(SP, THIS->count);
for (i=0; i < THIS->count; ++i) {
mPUSHn(THIS->data[i]);
}
}
else if (gimme == G_SCALAR) {
mXPUSHu(THIS->count);
}

Perl:

my $count = $C->getElements();
say $count;
my @array = $C->getElements();
say for @array;

注意:按sv_2mortal递减的refcnt被延迟,直到调用方有机会递增refcnt。

最新更新