On Sat, May 01, 2004 at 08:15:59AM +0200, Tassilo von Parseval wrote:
> Storing a pointer to the parent object (which would have to be the Perl
> scalar and not the underlying C struct) is probably the point where you
> will have to leave the typemap trail locally. You might need both the
> Perl scalar and the C structure referencing it and therefore do the
> conversion manually. In my module I have:

On my new() call I actually store the SvRV in my C object which I use in
child objects to decrement the ref count.  That works fine for child
objects that in the C API have a pointer back to the parent object.

But, in this case my child objects don't have that linkage.  So, my
options are to either update my C library to allow linking up to the
parent object, or, like you do below, malloc a new structure to hold
the pointer of the parent object.

I think the reason I added a place to hold the SvRV in my C struct was so I
could make use of the typemaps and use those simple method calls in the xs
code. Then use a special function in my DESTROY when I needed to get to the
parent object to decrement its refcount.

So for Perl code:

   my $search = SWISH::API->new( $index_name );
   my $results = $search->query( $some_user_query );

And when $results goes out of scope:

void
DESTROY(results)
    SW_RESULTS results

    CODE:
        if ( results )
        {
            SV *parent = (SV *)SwishResults_parent( results );
            Free_Results_Object( results );
            SvREFCNT_dec( parent );
        }

But, say I want to do it as in your example  -- by malloc a new
structure to contain the object and its parent.

In the methods on the new child object do you manually pull out your
"payload" data, or do you somehow have a typemap that will do that work
for you?  I seem to be obsessed with keeping my methods very simple:

int
SwishHits(self)
    SW_RESULTS self

Which is very handy way to create all of my methods.


Two other questions:  

In your example, where do you define the DBX_EMAIL struct?
Is that a struct that only exists in the Perl code?  So do you define
the struct at the top of your .xs file?

Second, you use XRETURN_EMPTY.  I see that I'm returning XSRETURN_UNDEF
which seems to work, but is likely wrong.  Can you explain when using
XSRETURN_UNDEF might break something when returning an empty list?

For example, here's how I first wrote that bit of code where I return
XSRETURN_UNDEF if there's nothing to return:

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

    PREINIT:
        char * CLASS = "SWISH::API::MetaName";
        SWISH_META_LIST meta_list;

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

        /* Check for an error -- typically this would be an invalid index name */
        /* Fix: calling with an invalid swish_handle will call progerr and abort */
        if ( SwishError( swish_handle ) )
            croak("%s %s", SwishErrorString( swish_handle ), SwishLastErrorMsg( 
swish_handle ) );

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


        while ( *meta_list )
        {
            /* Create a new object */
            SV *meta = sv_newmortal();
            sv_setref_pv( meta, CLASS, (void *)*meta_list );

            /* and push onto list */
            XPUSHs( meta );
            meta_list++;

            /* $$$ Need to bump the handle ref count here */
        }

Thanks very much for your help.  XS seems to be one of those things I
forget when away for a while.  I'm not sure if that's on purpose or not. ;)


-- 
Bill Moseley
[EMAIL PROTECTED]

Reply via email to