使用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
Run Code Online (Sandbox Code Playgroud)
它编译得很好,但是当我在perl中运行以下代码时:
my @d = $C->getPerlArray();
foreach(@d)
{
print "$_\n";
}
Run Code Online (Sandbox Code Playgroud)
它只是ARRAY(0x1408cdc)在我希望它打印一个数字列表时打印.
如何修改我的代码以正确传回perl数组?
ike*_*ami 10
Perl subs只能返回(0或更多)标量.当您尝试返回一个数组时(不会崩溃Perl!),默认的typemap会返回对该数组的引用.
请注意,您的程序也会泄漏内存(因为默认的typemap 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
Run Code Online (Sandbox Code Playgroud)
内存泄漏检查:
newAV) - 1 [延迟](sv_2mortal)+ 1(newRV)= 1 [延迟](由引用拥有)newRV) - 1 [延迟](sv_2mortal)= 0 [延迟]Perl的:
my $array = $C->getPerlArrayRef();
say for @$array;
Run Code Online (Sandbox Code Playgroud)
返回参考,方法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
Run Code Online (Sandbox Code Playgroud)
内存泄漏检查:
newAV)+ 0(newRV_noinc)= 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]));
}
Run Code Online (Sandbox Code Playgroud)
内存泄漏检查:
newAV)+ 0(newRV_noinc)= 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);
}
Run Code Online (Sandbox Code Playgroud)
Perl的:
my $count = $C->getElements();
say $count;
my @array = $C->getElements();
say for @array;
Run Code Online (Sandbox Code Playgroud)
注意:refcnt递减依次sv_2mortal延迟,直到调用者有机会递增refcnt.
| 归档时间: |
|
| 查看次数: |
296 次 |
| 最近记录: |