В моем файле 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
объект возвращается?
При использовании 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
то есть возвращать имя класса, если скаляр благословен, а не только базовый ссылочный тип.
Других решений пока нет …