Как эмулировать вызов &sname из XS?

Как подражать z суб поведение внутри XS к югу?

package XS;
sub hello {
    print "ARGS: >>@_<<\n";
    my $lvl;
    while( my @frame =  caller( $lvl++ ) ) {
        print ">>@frame[0..4]<<\n";
    }
}

sub z {
    &hello;
}

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

void
call_perl() {
    call_pv( "XS::hello", G_NOARGS );    
}

void
test(...)
    CODE:
        call_perl();

Но зовет XS::test(1,2,3) не передавайте никаких аргументов hello,

Выход:

ARGS: >><<
>>main -e 1 XS::hello <<

Здесь мы можем видеть, что $hasargs флаг не установлен из-за G_NOARG флаг, но почему @_ покраснел? Что я упустил?

UPD
Кажется, нашел половину ответа.

  1. Флаг G_NOARGS

    имеет эффект не создания массива @_ для подпрограммы Perl.

  2. когда XSUB называется perl, не создайте для него рамку (не помню, где это описано) и не заполняйте @_ для этого (это описано здесь косвенно)

    XSUB ссылаются на свои аргументы стека с помощью макроса ST(x)

Так что более точный вопрос будет:

Как размножаться XSUB складывать аргументы в PP подпрограмма?

ВНИМАНИЕ: я не могу просто использовать:

call_pv( "XS::hello", 0 );

Потому что это порядковый PP суб-вызов. И когда он возвращает XSUB аргументы стека будут заменены возвращаемым значением из XS::hello суб

int count =  call_pv( "XS::hello", 0 );
STAGAIN;
printf( "%s\n", SvPV_nolen( ST(0) ) );

Поэтому я поставляю G_NOARGS флаг, чтобы иметь возможность доступа XSUB стек аргументов после вызова PP суб

1 ответ

Вот код для XSUB как это сделать (ВНИМАНИЕ: в этом примере я не обрабатываю возвращаемые аргументы):

test(...)
CODE:
    AV *defav_old =  GvAV(PL_defgv);   # Save current @_

    AV *av = newAV();                  # Create new array
    av_extend(av, items -1);          
    AvREIFY_only(av);
    AvFILLp(av) =  items -1;
    Copy(MARK+1, AvARRAY(av), items, SV*); # Fill array by elements from stack

    GvAV(PL_defgv) =  av;     # point @_ to our new array


    PUSHMARK(SP);
    int count =  call_pv( "XS::Utils::hello", G_VOID | G_NOARGS );

    GvAV(PL_defgv) =  defav_old;  # Restore old @_
Другие вопросы по тегам