
marvin at rectangular
Jun 15, 2007, 5:35 PM
Post #3 of 6
(824 views)
Permalink
|
On Jun 15, 2007, at 1:52 PM, Nathan Kurz wrote: > On 6/15/07, Marvin Humphrey <marvin [at] rectangular> wrote: >> To subclass OrScorer, create MyOrScorer.c and MyOrScorer.h following >> the guidelines documented in the POD for devel/lib/BoilerPlater.pm. >> All you'll need is a constructor and a MyOrScorer_tally function. >> The rest will inherit. > > Got it, and it seems to Build correctly. Wow, hot damn. The BoilerPlater stuff came out well, but it wasn't and isn't really designed to be a public API. It arose out of necessity because the faked-up inheritance schemes that Dave Balmain was using with Ferret and I was using with KS 0.15 were messy and scaled poorly. The design was hashed out last fall on the Lucy developer's list. > First subclass subquestion: why do I actually need a constructor? In theory you could write an XS function that "reblessed" the object by changing the vtable pointer to point at a different one. MODULE = KinoSearch PACKAGE = KinoSearch::Search::MyOrScorer kino_MyORScorer* new(unused, sim, subscorers) SV *unused; kino_Similarity *sim; kino_VArray *subscorers; CODE: RETVAL = kino_ORScorer_new(sim, subscorers); RETVAL->_ = &KINO_MYORSCORER; /* <-------- rebless */ OUTPUT: RETVAL I've opted never to do that mainly because I want XS code to be limited to glue whenever possible. XS is powerful, but it's nasty and esoteric. Take a look at RichPostingScorer_new() -- it does exactly the same thing as that XS function above, but within a dedicated C constructor. > Is the class_name field actually used at runtime? Yes, absolutely. self->_->class_name is used all over the place, particularly when crossing the Perl/C boundary. Note that class_name is a member of the vtable, and not a member of the object struct. That means we don't have to waste space in every object with an extra pointer to the class name -- but also that the class name of an object is fixed. > And if I do need a > constructor, is it possible to piggyback on top of the constructor for > the class I'm inheriting from? Something like: > > MyORScorer *self = STEAL(MyORScorer, ORScorer_new(sim, > subscorers)); > (or BLESS, or RECREATE, RECLASS, whatever) Cool idea, but it would have to look slightly different, because of the limitations of C syntax. It would have to be either a function, or a multi-line macro like this: #define KINO_RECLASS(var, obj, type, vtable) \ type* var = (type*)(obj); \ var->_ = &(vtable) > I don't understand the innards of your vtable implementation well > enough to know quite what this would need to do, but if it is possible > it seems likely you've already done it somewhere but I just haven't > found where. Yes. Dynamic subclassing is supported via DynVirtualTable and the CREATE_SUBCLASS macro defined in MemManager.h. The implementation is fairly complex, which is unfortunate, because it doesn't accomplish very much -- it just allows the object to be associated with an arbitrary class name. :\ The feature is used by Schema, FieldSpec and Similarity to allow users to subclass via Perl without knowing anything about the underlying C objects. Ideally, our discussion will result in an improvement upon that scheme that will allow you to write your ORScorer subclass without touching BoilerPlater. Something like this: package MyORScorer; use base qw( KinoSearch::Search::ORScorer ); __PACKAGE__->register_c_method( tally => 'my_tally' ); use Inline => C << 'END_C'; kino_Tally* my_tally(kino_OrScorer *self) { /* ... */ } END_C Marvin Humphrey Rectangular Research http://www.rectangular.com/
|