On Fri, Oct 31, 2003 at 12:39:14PM +1100 Sisyphus wrote:Cool - thanks for the explanation. I've simplified the above slightly to use RETVAL itself as the SV *:
Steve Hay wrote:
So I tried rewriting my original example like this:
SV * hello() PREINIT: char *chartext; SV *svtext;
CODE: Newz(0, chartext, 13, char); strcpy(chartext, "Hello, world"); sv_usepvn(svtext, chartext, 13); RETVAL = svtext;
OUTPUT: RETVAL
However, I now find that when I call that from Perl ($greeting = Foo::hello()) then I get this error:
Modification of a read-only value attempted
I get a segfault, which is what I would expect. You only allocate memory
for the string but not for the SV to be returned.
[snip]
One could change it to:
SV *
hello()
PREINIT:
char *chartext;
SV *svtext;
CODE:
Newz(0, chartext, 13, char);
svtext = newSV(0);
strcpy(chartext, "Hello, world");
sv_usepvn(svtext, chartext, strlen(chartext));
RETVAL = svtext;
OUTPUT:
RETVAL
SV * hello() PREINIT: char *chartext;
CODE: Newz(0, chartext, 13, char); strcpy(chartext, "Hello, world"); RETVAL = newSV(0); sv_usepvn(RETVAL, chartext, 13);
OUTPUT: RETVAL
This still works fine.
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 *?
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?)
- Steve