Perl XS — не может вернуть новый пользовательский объект C ++ из вызова метода — вместо этого возвращает скалярное значение

В моем файле XS у меня есть:

Как мой новый метод:

matrix *
matrix::new( size_t ncols, size_t nrows )

который возвращает matrix объект, как это должно, и я могу вызывать методы.

Затем у меня есть вызов метода, который создает новый матричный объект и должен вернуть его как новую матрицу:

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

Однако возвращаемый тип matrix=SCALAR(0x122f81c) и поэтому я не могу вызвать какие-либо вызовы методов из этого объекта, так как интерпретатор perl, похоже, просматривает возвращаемый тип как тип скалярного значения вместо объекта ‘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 или любой другой файл, чтобы обеспечить matrix объект возвращается?

7

Решение

При использовании XS с C ++ препроцессор XS вставляет THIS например методы и CLASS для статических методов. Метод называется new рассматривается как статический метод. Это позволяет использовать полученные xsubs как методы экземпляра / методы класса по умолчанию: 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* возвращаемое значение либо.

Обратите внимание, что строчные имена пакетов должны использоваться только для прагматических пакетов (например, strict или же warnings). Пожалуйста, используйте CamelCase для ваших занятий.

Ваша попытка представить свою ценность для CLASS не удалось, потому что SvPV_nolen() преобразует ссылку в строку и не получает тип ссылки. То есть это эквивалентно "$m"не ref $m, Более правильной альтернативой было бы использование sv_ref():

char* CLASS = SvPV_nolen(sv_ref(NULL, THIS, true));

Третий параметр sv_ref() заставляет эту функцию работать как функция Perl refто есть возвращать имя класса, если скаляр благословен, а не только базовый ссылочный тип.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]