(by the way, i'm subbed to the list, there's no need to reply-to-all.)

On Wednesday, May 26, 2004, at 04:51 PM, Bill Moseley wrote:

On Wed, May 26, 2004 at 01:35:30PM -0400, muppet wrote:

what's the "secondary routine"? the code you called with call_pv()? in that case they returned the values to your XS code, and you are now responsible for doing something with them. are you wanting simply to pass them straight back to your caller? or are you talking about using them in your xsub?

Pass them back to the caller.

forgive me if i've missed something basic, but why do this in an xsub? wouldn't


   sub return_list { return secondary_sub (@_) }

suffice?


void
return_list( var_a, var_b )
    char *var_a
    char *var_b
    PPCODE:
        PUSHMARK(SP);
        XPUSH( (SV *)var_a );
        XPUSH( (SV *)var_b );

erm, i think you'd rather be using ST(0) and ST(1) there, unless var_a and var_b are actually just defined as SV* instead of char*.


        PUTBACK;
        call_pv("Foo::secondary_function", G_ARRAY );
        SPAGAIN;

for some reason, i had tried this earlier today and gotten nothing returned; now it works. i wonder what i had been doing wrong.



So "secondary_function" pushes any number of thingies onto the stack and returns them to perl space. Like I said, the stack is a mystery to me, so I'm not clear how perl knows how many Foo::Bla objects are on the stack and how many to place in @list.

that's what marks and the stack pointer are for.

That is, I wonder if I need to check the return value from call_pv (the number of items pushed on the stack, right?) and then in "return_list" use that number to tell perl how many items I'm returning.

Sorry, that's not very clear, but hopefully the code makes it clear what I'm attempting.

BTW -- I also was wondering how best to check for leaks in the Perl/XS code -- make sure all my objects are destroyed like I expect.

(i have a fair amount of experience with calling perl code from C and XS, but not with attempting to pass lists through like this, so i find the problem interesting, and i may be wrong.)


i took a simplistic approach, using a helper function implemented in perl returning a random number of objects whose destructors will print a message when called. then if the messages are printed at the right time, the memory management it handled correctly. :-)

create a new module Foo with h2xs, and then add these bits in the proper places:

in Foo.pm:
  package RandNum;
  sub new {
        my $class = shift;
        my $num = rand;
        return bless \$num, $class
  }
  sub DESTROY {
        my $self = shift;
        warn "killing $$self\n";
  }
  package Foo;

  sub _bar {
        my @vars = ();
        foreach (0..(int rand 20)) {
                push @vars, new RandNum;
        }
        return @vars;
  }

in Foo.xs:
  void
  get_list (SV * a, SV * b)
      PPCODE:
        PUSHMARK (SP);
        // push two things onto the stack
        XPUSHs (a);
        XPUSHs (b);
        PUTBACK;
        // pops those two things from the stack, and pushes n
        call_pv("Foo::_bar", G_ARRAY);
        SPAGAIN;
        // we don't alter the stack, so it still has n on it.
        // don't try this at home; i got this math from macros in XSUB.h:
        warn ("stack size: %d\n", PL_stack_sp - PL_stack_base);


then in a test script:

  use Foo;
  use Data::Dumper;
  print Dumper([Foo::get_list (1, 3)]);

this prints:

  tetsuo:~/Foo$ make && perl -I blib/lib -I blib/arch testfoo.pl
  stack size: 4
  $VAR1 = [
            bless( do{\(my $o = '0.745608798499358')}, 'RandNum' ),
            bless( do{\(my $o = '0.831126170788544')}, 'RandNum' ),
            bless( do{\(my $o = '0.337258020777046')}, 'RandNum' ),
            bless( do{\(my $o = '0.130808133151717')}, 'RandNum' )
          ];
  killing 0.337258020777046
  killing 0.831126170788544
  killing 0.745608798499358
  killing 0.601354444722773
  leaving
  tetsuo:~/Foo$


so, the moral of the story: your code works correctly. the stuff gets destroyed at the right time. the perl stack is not magical, it's just a C array of SVs, managed by a number of pointers and macros.


i have not verified that this works when you're deep in a series of calls with a bunch of stuff already on the stack.


--
I bring the rock, and provided it is fiscally responsible, I will bring the funk as well. And that's fo-shizzle.
-- Saturday Night Live




Reply via email to