Steve Hay <[EMAIL PROTECTED]> writes: >I understand the second case there -- when the xsub is called as >"hello(1)" -- but that leaves me wondering what ST(0) was in the case >where the xsub was called without arguments.
It is a stack - a hunk of memory. So if you don't have any args one it is: - the SV returned by last thing caller called, or - if that didn't return anything then 1st arg of last call, or - some arg passed/returned by someone or - garbage that will give you a segfault if nothing has been called Nth arg of the caller. > >Presumably I should therefore rewrite the above as: > > void > hello() > PREINIT: > char *chartext; > > CODE: > Newz(0, chartext, 13, char); > strcpy(chartext, "Hello, world"); > ST(0) = newSV(0); > sv_usepvn(ST(0), chartext, 13); > XSRETURN(1); > >to be sure of what ST(0) really is. Yes. By the way what is the reason you do a PREINIT which does no init rather than CODE: { char *chartext; ... } ? >After a quick skim-read of the perlcall manpage I tried writing another >xsub called callhello() that calls the hello() xsub above and simply >returns whatever hello() returned: > > void > callhello() > CODE: > dSP; > PUSHMARK(SP); PUTBACK; // not essential with no args > call_pv("Foo::hello", G_SCALAR); SPAGAIN; // always required > ST(0) = POPs; PUTBACK; // Not essential if returning next ... > XSRETURN(1); > >However, when I call that from Perl ("my $greeting = Foo::callhello()") >I find that callhello() returned 1 rather than "hello". You need in general the PUTBACK/SPAGAIN when stack pointer has changed. In particular calling something may grow the stack. As POPs changes stack pointer it is perhaps less risky to your sanity to do things in stages: call_pv(...); // stack may move SPAGAIN; // Get current stack val = POPs; // stack changes PUTBACK; // update stack ST(0) = val; XSRETURN(1); > >(Am I correct in thinking that I don't require the "ST(0) = newSV(0)" >bit this time since I'm assigning something else to ST(0) anyway rather >than telling an already extant ST(0) to "use" a char * elsewhere.) > >I then tried again, this time passing an argument to the hello() xsub >(after changing it as before to accept arguments): > > void > callhello() > CODE: > dSP; > ENTER; > SAVETMPS; > PUSHMARK(SP); > XPUSHs(sv_2mortal(newSViv(1))); > PUTBACK; > call_pv("Foo::hello", G_SCALAR); > ST(0) = POPs; > FREETMPS; > LEAVE; > XSRETURN(1); > >This time callhello() works, returning "Hello, world". This is most likely because this time YOUR XPUSHs grew the stack, not the call, so SP is still the value you PUTBACK. But there is a new snag with that code. You have added a SAVETMPS/FREETMPS pair. So if Foo::hello had used the 'mortal' style the SV you re-used will be free-d when you hit the FREETMPS, and callhello's caller would see an undef. > >Does this confirm my suspicion that the hello() xsub doesn't have a >"free" item (ST(0)) on the stack when called from another xsub? > >As a further test I tried having hello() extend the stack by one to be >safe if it is called with no arguments. Here's the new hello(): > > void > hello(...) > PREINIT: > char *chartext; > > CODE: > Newz(0, chartext, 13, char); > strcpy(chartext, "Hello, world"); > if (items == 0) > { > PerlIO_printf(PerlIO_stdout(), "No args\n"); > EXTEND(SP, 1); > } > ST(0) = newSV(0); > sv_usepvn(ST(0), chartext, 13); > XSRETURN(1); > >However, when I called that from callhello() with no arguments, >callhello() *still* returned 1 rather than "Hello, world", so perhaps my >suspicion is not confirmed after all, and I've buggered something else >up instead! (The "No args" message was printed out, so the EXTEND(SP, >1) was definitely done.) > >- Steve