加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

arrays – perl xs – 从c数组返回perl数组

发布时间:2020-12-15 21:50:56 所属栏目:大数据 来源:网络整理
导读:使用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 它编译得很好
使用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 subs只能返回(0或更多)标量.当您尝试返回一个数组时(不可能崩溃Perl!),默认的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

内存泄漏检查:

>数组的refcnt:1(newAV)-1 [延迟](sv_2mortal)1(newRV)= 1 [延迟](由参考所有)
>参考文献的refcnt: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(由引用拥有)
>参考文献的refcnt: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(由引用拥有)
>参考文献的refcnt: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.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读