Tassilo von Parseval wrote:

On Fri, Oct 31, 2003 at 09:34:46AM +0000 Steve Hay wrote:


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.

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.

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.




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.

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);
           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



Reply via email to