>>By the way what is the reason you do a PREINIT which does no init rather >>than >> >>CODE: >> { >> char *chartext; >> ... >> } >> >>? >> >I once fell foul of the problem described in the PREINIT entry in the >perlxs manpage, namely: "If a variable is declared inside a CODE: >section it will follow any typemap code that is emitted for the input >parameters. This may result in the declaration ending up after C code, >which is C syntax error." > >I was very new to XS at the time (even newer than I am now ;), and was >confused for ages by it. I've used PREINIT to declare all my variables >ever since then just to play it safe. > >Is there a problem with using PREINIT all the time in this way?
Don't know - but I tend to use {} after CODE: - which creates a new C block which can declare things. >At this point I have: > > void > hello(...) > PREINIT: > char *chartext; > > CODE: > Newz(0, chartext, 13, char); > strcpy(chartext, "Hello, world"); > ST(0) = newSV(0); ST(0) = sv_newmortal(); // like above but does sv_2mortal for you > sv_usepvn(ST(0), chartext, 13); > XSRETURN(1); > > void > callhello() > PREINIT: > SV *val; > > CODE: > dSP; > PUSHMARK(SP); > PUTBACK; > call_pv("Foo::hello", G_SCALAR); > SPAGAIN; > val = POPs; > PUTBACK; > ST(0) = val; > PUTBACK; // this one is not necessary > XSRETURN(1); > >So it seems that you can, after all, assign to ST(0) even when an xsub >is called with no arguments from another xsub. I'm puzzled by that: I >thought that before assigning to ST(0), ..., ST(n) you had to call >EXTEND(SP, n + 1). Calling EXTEND(SP, n) would suffice when the xsub is >called from Perl, but not when called from another xsub. In this case >we are calling from another xsub; n is 0, so I thought I would have >needed to call EXTEND(SP, 1) first. I think there is one free slot - but I may be wrong. > >There's one other problem too: The above code leaks if I call >callhello() a million times over in a for loop. Where is the leak >coming from? You haven't made its return value mortal. >> >The SAVETMPS/FREETMPS was to have the (mortal) argument that I'm passing >to Foo::hello free()'d; I'd forgotten that it free()'s any mortal return >values as well. > >Here's the example with hello() returning a mortal SV * that has its own >char * space: > > void > hello(...) > PREINIT: > char *chartext; > > CODE: > Newz(0, chartext, 13, char); > strcpy(chartext, "Hello, world"); > ST(0) = sv_2mortal(newSVpv(chartext, 13)); > XSRETURN(1); > > void > callhello() > PREINIT: > SV *val; > > CODE: > dSP; > ENTER; > SAVETMPS; > PUSHMARK(SP); > XPUSHs(sv_2mortal(newSViv(1))); > PUTBACK; > call_pv("Foo::hello", G_SCALAR); > SPAGAIN; > val = POPs; > PUTBACK; > ST(0) = val; > PUTBACK; > FREETMPS; > LEAVE; > XSRETURN(1); > >It does indeed result in callhello()'s caller getting undef. > >So how would I avoid coming a cropper like that? >I want the arguments >that callhello() passes to hello() to be freed before callhello() >returns, but I don't want hello()'s return value to be free()'d then as >well. > >This seems to work: > > ... > call_pv("Foo::hello", G_SCALAR); > SPAGAIN; > val = newSVsv(POPs); > PUTBACK; > FREETMPS; > LEAVE; > ST(0) = sv_2mortal(val); > PUTBACK; > XSRETURN(1); > >Is that OK That moral equivalent of what perl does ... >or is there a more efficient way to do this? Slightly. val = POPs; PUTBACK; SvREFCNT_inc(val); // save it from destruction FREETMPS; LEAVE; // now back in outer "scope". ST(0) = sv_2mortal(val); XSRETURN(1); > >- Steve