perl xs - 不能 return 来自方法调用的新自定义 c++ 对象 - returns 标量值
perl xs - can't return a new custom c++ object from method call - returns scalar value instead
在我的 XS 文件中有:
作为我的新方法:
matrix *
matrix::new( size_t ncols, size_t nrows )
哪个 return 是一个 matrix
对象,我可以调用方法。
然后我有一个方法调用,它创建了一个新的矩阵对象并且应该 return 它作为一个新的矩阵:
matrix *
matrix::getInnerMatrix( )
PREINIT:
char * CLASS = (char *)SvPV_nolen(ST(0));
CODE:
RETVAL = static_cast<matrix*>(THIS->matrix::getInnerMatrix());
OUTPUT:
RETVAL
然而,returned 类型是 matrix=SCALAR(0x122f81c)
,因此我无法从该对象调用任何方法调用,因为 perl 解释器似乎将 returned 类型视为标量值类型而不是 'matrix' 对象。这是一个测试脚本:
$m1 = matrix::new(matrix,4,4);
@arr = ( 1 .. 16 );
$aref = [@arr];
$m1->assign_aref($aref);
my $m2 = $m1->getInnerMatrix();
print ref $m1; # returns "matrix" (like it should)
print "\n\n";
print ref $m2; # returns "matrix=SCALAR(0x122f81c)" (wrong)
这是我的类型图:
TYPEMAP
matrix * O_MATRIX
OUTPUT
O_MATRIX
sv_setref_pv( $arg, CLASS, (void*)$var );
INPUT
O_MATRIX
if ( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) ) {
$var = ($type)SvIV((SV*)SvRV( $arg ));
}
else {
warn( \"${Package}::$func_name() -- ${var} not a blessed SV reference\" );
XSRETURN_UNDEF;
}
我必须在我的 XS 文件或任何其他文件中进行哪些更改才能确保 return 编辑的是纯 matrix
对象?
在 C++ 中使用 XS 时,XS 预处理器为实例方法插入 THIS
,为静态方法插入 CLASS
。名为 new
的方法被视为静态方法。这允许生成的 xsubs 默认用作实例 methods/class 方法:matrix->new
和 $m->getInnerMatrix()
.
您的类型映射使用 CLASS
变量,实例方法未提供该变量。在你的情况下,我会在类型映射中硬编码包名称:
OUTPUT
O_MATRIX
sv_setref_pv( $arg, "matrix", (void*)$var );
当该类型的参数未用作调用者时,也会使用类型映射。例如。考虑这个 xsub:
matrix*
some_other_xsub(x)
int x
这里也不会有 CLASS
变量用于 matrix*
return 值。
请注意,小写包名称只能用于 pragma 包(如 strict
或 warnings
)。请为您的 classes 使用 CamelCase。
您尝试为 CLASS
提供您自己的值失败,因为 SvPV_nolen()
将引用字符串化并且没有获取引用类型。 IE。它相当于 "$m"
,而不是 ref $m
。更正确的替代方法是使用 sv_ref()
:
char* CLASS = SvPV_nolen(sv_ref(NULL, THIS, true));
sv_ref()
的第三个参数使这个函数像 Perl 函数 ref
一样工作,即 return 如果标量被祝福, class 名称,而不仅仅是基础引用类型。
在我的 XS 文件中有:
作为我的新方法:
matrix *
matrix::new( size_t ncols, size_t nrows )
哪个 return 是一个 matrix
对象,我可以调用方法。
然后我有一个方法调用,它创建了一个新的矩阵对象并且应该 return 它作为一个新的矩阵:
matrix *
matrix::getInnerMatrix( )
PREINIT:
char * CLASS = (char *)SvPV_nolen(ST(0));
CODE:
RETVAL = static_cast<matrix*>(THIS->matrix::getInnerMatrix());
OUTPUT:
RETVAL
然而,returned 类型是 matrix=SCALAR(0x122f81c)
,因此我无法从该对象调用任何方法调用,因为 perl 解释器似乎将 returned 类型视为标量值类型而不是 'matrix' 对象。这是一个测试脚本:
$m1 = matrix::new(matrix,4,4);
@arr = ( 1 .. 16 );
$aref = [@arr];
$m1->assign_aref($aref);
my $m2 = $m1->getInnerMatrix();
print ref $m1; # returns "matrix" (like it should)
print "\n\n";
print ref $m2; # returns "matrix=SCALAR(0x122f81c)" (wrong)
这是我的类型图:
TYPEMAP
matrix * O_MATRIX
OUTPUT
O_MATRIX
sv_setref_pv( $arg, CLASS, (void*)$var );
INPUT
O_MATRIX
if ( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) ) {
$var = ($type)SvIV((SV*)SvRV( $arg ));
}
else {
warn( \"${Package}::$func_name() -- ${var} not a blessed SV reference\" );
XSRETURN_UNDEF;
}
我必须在我的 XS 文件或任何其他文件中进行哪些更改才能确保 return 编辑的是纯 matrix
对象?
在 C++ 中使用 XS 时,XS 预处理器为实例方法插入 THIS
,为静态方法插入 CLASS
。名为 new
的方法被视为静态方法。这允许生成的 xsubs 默认用作实例 methods/class 方法:matrix->new
和 $m->getInnerMatrix()
.
您的类型映射使用 CLASS
变量,实例方法未提供该变量。在你的情况下,我会在类型映射中硬编码包名称:
OUTPUT
O_MATRIX
sv_setref_pv( $arg, "matrix", (void*)$var );
当该类型的参数未用作调用者时,也会使用类型映射。例如。考虑这个 xsub:
matrix*
some_other_xsub(x)
int x
这里也不会有 CLASS
变量用于 matrix*
return 值。
请注意,小写包名称只能用于 pragma 包(如 strict
或 warnings
)。请为您的 classes 使用 CamelCase。
您尝试为 CLASS
提供您自己的值失败,因为 SvPV_nolen()
将引用字符串化并且没有获取引用类型。 IE。它相当于 "$m"
,而不是 ref $m
。更正确的替代方法是使用 sv_ref()
:
char* CLASS = SvPV_nolen(sv_ref(NULL, THIS, true));
sv_ref()
的第三个参数使这个函数像 Perl 函数 ref
一样工作,即 return 如果标量被祝福, class 名称,而不仅仅是基础引用类型。