perl xs - return 来自 c 数组的 perl 数组
perl xs - return perl array from c array
我正在尝试使用 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 只能 return(0 个或更多)标量。当您尝试 return 一个数组时(如果不使 Perl 崩溃是不可能的!),默认类型映射 return 改为对该数组的引用。
请注意,您的程序也会泄漏内存(因为 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
内存泄漏检查:
- 数组的引用: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
内存泄漏检查:
- 数组的引用: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]));
}
内存泄漏检查:
- 数组的引用: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;
注意:refcnt 减少 sv_2mortal
被延迟,直到调用者有机会增加 refcnt。
我正在尝试使用 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 只能 return(0 个或更多)标量。当您尝试 return 一个数组时(如果不使 Perl 崩溃是不可能的!),默认类型映射 return 改为对该数组的引用。
请注意,您的程序也会泄漏内存(因为 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
内存泄漏检查:
- 数组的引用: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
内存泄漏检查:
- 数组的引用: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]));
}
内存泄漏检查:
- 数组的引用: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;
注意:refcnt 减少 sv_2mortal
被延迟,直到调用者有机会增加 refcnt。