perl xs - 无法从方法调用返回新的自定义c ++对象 - 而是返回标量值

7 c++ perl xs

在我的XS文件中,我有:

作为我的新方法:

matrix *
matrix::new( size_t ncols, size_t nrows )
Run Code Online (Sandbox Code Playgroud)

它返回一个matrix像它应该的对象,我可以调用方法.

然后我有一个方法调用,它创建一个新的矩阵对象,并应该将其作为一个新的矩阵返回:

matrix *
matrix::getInnerMatrix( )
    PREINIT:
        char *  CLASS = (char *)SvPV_nolen(ST(0));
    CODE:
        RETVAL = static_cast<matrix*>(THIS->matrix::getInnerMatrix());
    OUTPUT:
        RETVAL
Run Code Online (Sandbox Code Playgroud)

但是返回的类型是matrix=SCALAR(0x122f81c)因为我无法调用来自此对象的任何方法调用,因为perl解释器似乎将返回的类型视为标量值类型而不是"矩阵"对象.这是一个测试脚本:

$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)
Run Code Online (Sandbox Code Playgroud)

这是我的typemap:

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;
    }
Run Code Online (Sandbox Code Playgroud)

我必须在XS文件或任何其他文件中进行哪些更改以确保matrix返回纯对象?

amo*_*mon 4

将 XS 与 C++ 结合使用时,XS 预处理器会插入THIS实例方法和CLASS静态方法。调用的方法new被视为静态方法。这允许默认情况下将生成的 xsub 用作实例方法/类方法:matrix->new$m->getInnerMatrix()

您的类型映射使用CLASS未为实例方法提供的变量。在你的情况下,我会在类型映射中硬编码包名称:

OUTPUT
O_MATRIX
    sv_setref_pv( $arg, "matrix", (void*)$var );
Run Code Online (Sandbox Code Playgroud)

当该类型的参数不用作调用者时,也会使用类型映射。例如考虑这个 xsub:

matrix*
some_other_xsub(x)
    int x
Run Code Online (Sandbox Code Playgroud)

这里也不会有返回值CLASS的变量matrix*

请注意,小写的包名称只能用于 pragma 包(例如strictwarnings)。请在您的课程中使用驼峰命名法。

您尝试提供自己的值CLASS失败,因为SvPV_nolen()对引用进行字符串化并且未获取引用类型。即它相当于"$m",而不是ref $m。更正确的选择是使用sv_ref()

char* CLASS = SvPV_nolen(sv_ref(NULL, THIS, true));
Run Code Online (Sandbox Code Playgroud)

第三个参数 使sv_ref()该函数像 Perl 函数一样工作ref,即如果标量被祝福则返回类名,而不仅仅是底层引用类型。