On Fri, Oct 31, 2003 at 09:34:46AM +0000 Steve Hay wrote: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.
That contrasts interestingly with the void xsub case:
void hello() PREINIT: char *chartext;
CODE: Newz(0, chartext, 13, char); strcpy(chartext, "Hello, world"); sv_usepvn(ST(0), chartext, 13); XSRETURN(1);
which works without having to say "ST(0) = newSV(0)". Does that mean that ST(0) is already an allocated SV *?
It could be, but what you do is dangerous and in fact uncontrollable. ST(0) contains a totally unrelated SV. Change the abobe code to
... sv_dump(ST(0)); sv_usepvn(ST(0), chartext, 13); ...
and you will see for (hello()) for instance
SV = PVGV(0x81494b0) at 0x818b650 REFCNT = 2 FLAGS = (GMG,SMG,MULTI) IV = 0 NV = 0 MAGIC = 0x819a240 MG_VIRTUAL = &PL_vtbl_glob MG_TYPE = PERL_MAGIC_glob(*) MG_OBJ = 0x818b650 NAME = "hello" NAMELEN = 5 [ etc. ]
and compare it to the output you get when you say 'hello(1)' (change : the prototype to 'SV*\nhello(...)' to allow passing parameters in):
SV = IV(0x81a2298) at 0x8128bd4 REFCNT = 1 FLAGS = (IOK,READONLY,pIOK) IV = 1 Modification of a read-only value attempted at -e line 1.
Spot the system behind it? ST(0) refers to the first value of the stack...that could be a value that you passed to the subroutine or in fact anything else you don't have control over.
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.
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:
If so, is that always the case? In a previous thread discussing returning lists from xsubs (http://www.perldiscuss.com/article.php?id=1112&group=perl.xs) it was pointed out that when using EXTEND / PUSHs you get one free push if the xsub was called from Perl, but don't if it was called from another xsub. What I'm wondering is would ST(0) still be a preallocated SV * if the xsub was called from another xsub?
(I would try it out to see, but I don't know how to call an xsub from another xsub! How does one do that?)
An xsub should just be an ordinary Perl subroutine so you call it like any other subroutine, see perlcall.pod. A good template is:
/* call Perl function */
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
/* push the arguments for the function onto the stack */
XPUSHs(sv_2mortal(byte));
PUTBACK;
/* call it in void context */ (void)call_pv("Package::some_function", G_VOID); FREETMPS;
When the called function should return values, use G_SCALAR or G_ARRAY for the context. You find the returned values on the stack after that, so you can pop them off. The call_?? return the number of elements that the called function returned.
void callhello() CODE: dSP; PUSHMARK(SP); call_pv("Foo::hello", G_SCALAR); ST(0) = POPs; XSRETURN(1);
However, when I call that from Perl ("my $greeting = Foo::callhello()") I find that callhello() returned 1 rather than "hello".
(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".
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