Well, it's been three weeks and I'm finally getting back to this.
I think it's working fine, but I'm asking for a review to make sure I'm
not doing anything stupid.


To review, I needed to track a parent object to manage reference
counts.  In perl, it might look like:

   my $parent = Foo->new;
   my @list = $parent->list;

   print list[0]->Name;  # C call.

where I don't want $parent destroyed until all elements of @list are
gone.

So, with your help Tassilo, I made each element of @list a struct that contains
both the pointer to the $parent SV and also the pointer I need for
calling the Name() function in my C code.  Upon DESTROY I free that
struct and decrement that parent's ref count.

I have two questions, and a comment:

First, I'm not clear if I'm dealing with the Perl stack correctly.  So,
could you (or someone) look that over, please?

Second, how do I make sure memory is going away like I expect?  Is there
a tool that will tell me if I've got any allocated SVs when my test
program wants to exit?  Trying to avoid any leaks, of course.


And my comment: I had wanted to keep my XSUB code clean by using
typemaps -- that is, have method calls look only like:

  const char *
  SwishMetaName( meta )
    SW_META meta

That turned out to be trivial using a typemap and a PREFIX.

Code:

Back to my first question.  In my XSUB I have one function call another
function that does the work using call_pv().  I'll just show the code,
but what I'm not clear on is if I'm dealing with the stack correctly.
I'm *not* using the return value of call_pv(), but I wonder if I need to
extend the stack before returning.  I'm using XPUSHs, but I'm not clear
if that's enough when one function calls another.

In short -- I just want to make sure I've got the stack correctly
handled.



/* At the top of the .xs file -- container object */

typedef struct {
    SV          *handle_sv;     /* Parent SV for DESTROY */
    SW_META     meta;           /* meta description C pointer */
} META_OBJ;



/* SW_HANDLE is a typemap of O_OBJECT, so that gets me the C pointer */


void
SwishMetaList( swish_handle, index_name )
    SW_HANDLE swish_handle
    char *index_name

    PREINIT:
        SWISH_META_LIST meta_list;

    PPCODE:
        /* Grab the list of pointers */
        meta_list = SwishMetaList( swish_handle, index_name );

        PUSHMARK(SP) ;
        XPUSHs( (SV *)swish_handle );
        XPUSHs( (SV *)meta_list );
        XPUSHs( (SV *)"SWISH::API::MetaName");
        PUTBACK ;           /* lets perl know how many parameters are here */

        call_pv("SWISH::API::push_meta_list", G_ARRAY );
        SPAGAIN;

Do I need to check the return value of call_pv() and use that to set the
stack size?  The perl stack is somewhat, no, mostly black magic to me.


Below is the code that does the real work.  It's called by four
XSUB functions like above.  Do I need to call XSRETURN(n) where n is
the number of elements on the array when exiting the function?

The function SwishGetRefPtr() returns the SV associated to the
swish_handle, if you are wondering.

void
push_meta_list( s_handle, m_list, m_class )
    SV *s_handle
    SV *m_list
    SV *m_class

    PREINIT:
        SW_HANDLE swish_handle;
        SWISH_META_LIST meta_list;
        char *class;

    PPCODE:
        class = (char *)m_class;
        swish_handle = (SW_HANDLE)s_handle;
        meta_list = (SWISH_META_LIST)m_list;


        /* Make sure a list is returned and it's not empty */
        if ( !meta_list || !*meta_list )
            XSRETURN_EMPTY;


        while ( *meta_list )
        {
            /* Create a new structure for storing the meta description and the parent 
SV */
            META_OBJ *object = (META_OBJ *)safemalloc(sizeof(META_OBJ));

            /* Store the meta entry */
            object->meta = *meta_list;

            /* Store the and bump the swish_handle SV */
            object->handle_sv = (SV *)SwishGetRefPtr( swish_handle );
            SvREFCNT_inc( object->handle_sv );

            /* And create the Perl object and assign the object to it */
            SV *o = sv_newmortal();
            sv_setref_pv( o, class, (void *)object );

            /* and push onto list */
            XPUSHs( o );

            meta_list++;
        }


Then later on, here's the class.  META_OBJ is just a O_OBJECT typemap
so that just give me the structure.

SW_META is a slightly modified typemap to give me the ->meta element
from that structure, which makes my method calls very easy to write in
the XSUB.



MODULE = SWISH::API       PACKAGE = SWISH::API::MetaName  PREFIX = SwishMeta

void
DESTROY ( self )
    META_OBJ *self
    CODE:
        SvREFCNT_dec( self->handle_sv );
        safefree( self );


const char *
SwishMetaName( meta )
    SW_META meta

int
SwishMetaType( meta )
    SW_META meta

int
SwishMetaID( meta )
    SW_META meta









-- 
Bill Moseley
[EMAIL PROTECTED]

Reply via email to