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]