I have an XS module, mostly following the models in Extending and Embedding Perl. I use a T_PTROBJ type,
and keep everything I need in a dynamically allocated C structure, whose address is the T_PTROBJ object.
But as I add functionality, it's a nuisance to have to keep adjusting the contents of the structure. I'd like to be able to do things that are not so time critical in plain perl, but still get directly to the methods defined in the XS module. If I add an HV * to my C structure, I can initialize it with an anonymous hash that acts somewhat like the usual pure-perl blessed object, for holding (and hiding) arbitrary state information. So my skeletal XS code looks something like
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include <am_common.h>
#include "const-c.inc"
MODULE = AddrMatch PACKAGE = AddrMatch
INCLUDE: const-xs.inc
AddrMatch *
new_xs(class, stash)
char * class
HV * stash
PREINIT:
AddrMatch *amd;
CODE:
amd = malloc(sizeof(AddrMatch));
SvREFCNT_inc((SV *) stash);
amd->stash = stash;
RETVAL = amd;
OUTPUT:
RETVAL
MODULE = AddrMatch PACKAGE = AddrMatchPtr
void
DESTROY(amd)
AddrMatch * amd
CODE:
SvREFCNT_dec((SV *)(amd->stash));
free(amd);
HV *
stash(amd)
AddrMatch * amd
CODE:
RETVAL = amd->stash;
OUTPUT:
RETVAL
where the
stash structure element gives me a place to stash my perl-level state. Then my AddrMatch.pm can do something like
package AddrMatch;
sub new {
my %state = ( what => "ever" );
my $amd = AddrMatch->xs_new(\%state);
return $amd;
}
# then, later, recover the perl-ish state with
package AddrMatchPtr;
sub something {
my $self = shift;
my $state = $self->stash();
my $what = $state->{what};
$state{how} = "now";
}
So the question (there must be a question in here somewhere) is, can this be done more elegantly in some other way? This isn't too onerous, and it makes it quite easy to change my mind about whether some method is implemented in pure perl, or is worth coding into the XS module. But I'd be happy to do it more simply, if possible.