On Apr 26, 2008, at 12:55 PM, Marvin Humphrey wrote:

This isn't a truly hard problem. There are definitely many ways to make this introspection data available using C. But all the ways I've thought of so far are ugly.

I've gotten this working.  On its own, it's mildly ugly -- not too bad.

Things are improving step by step. At first, you couldn't override anything. Then you could implement abstract methods using the host language. Now you can override public methods.

There's one significant problem left that I'm aware of: Perl's SUPER mechanism is broken with the vtable override.

Say you use the host language to override a method which was implemented in C. The original binding invoked the implementing function via the vtable. The override has now changed that vtable pointer to be a callback. If you invoke SUPER from the subclass, it invokes the callback, which invokes the native method again, and you end up in an infinite loop.

  sub serialize {
     my ( $self, $outstream ) = @_;
     $self->SUPER::serialize($outstream); # BOOM! Infinite recursion.
     ...
  }

The solution, I believe, is to have the XS bindings not invoke via the vtable, but instead invoke the implementing function directly. Unfortunately, that means a lot more binding code, because each override requires its own binding.

Now:

   MODULE = KinoSearch   PACKAGE = KinoSearch::Index::PostingList

   chy_u32_t
   get_doc_num(self)
      kino_PostingList *self;
   CODE:
      RETVAL = Kino_PList_Get_Doc_Num(self);
   OUTPUT: RETVAL

Fixed:

   MODULE = KinoSearch   PACKAGE = KinoSearch::Index::PostingList

   chy_u32_t
   get_doc_num(self)
      kino_PostingList *self;
   CODE:
      RETVAL = kino_PList_get_doc_num(self);
   OUTPUT: RETVAL

   MODULE = KinoSearch   PACKAGE = KinoSearch::Index::SegPostingList

   chy_u32_t
   get_doc_num(self)
      kino_SegPostingList *self;
   CODE:
      RETVAL = kino_SegPList_get_doc_num(self);
   OUTPUT: RETVAL

   MODULE = KinoSearch   PACKAGE = KinoSearch::Index::MultiPostingList

   chy_u32_t
   get_doc_num(self)
      kino_MultiPostingList *self;
   CODE:
      RETVAL = kino_MultiPList_get_doc_num(self);
   OUTPUT: RETVAL

Fortunately, most of the binding code gets auto-generated these days, so once the auto-generation code gets patched the suffering will primarily take the form of slower compiles rather than increased maintenance costs.

Marvin Humphrey
Rectangular Research
http://www.rectangular.com/

Reply via email to