Re: GType::register RFE



Brett Kosinski said:
Doh!
s/Glib::Object::Subclass/GType::register/
*sigh*

i knew what you meant.  the module is just a thin wrapper around
Glib::Type::register at this point, anyway.


Is there any way Glib::Object::Subclass can be enhanced to allow one to
pass in custom base_init and class_init functions (which would be executed
before/after the built-in ones)?  I'm trying to implement element
subclassing in GStreamer, and in order to do it properly, I need to be
able to do this.

i made a few assumptions when writing Glib::Type::register:

1) we're only going to be creating GObject derivatives.[1]
2) classes won't be finalized (because perl does not undefine code)
3) class_init will run only once (follows from 2)

given 2 and 3, there's no need to make the code wait around for class_init to
run, so we ref the class right there in register.  this allows us to simplify
the programmer's interface to it, and take signals and properties as creation
parameters rather than requiring you to code those directly.

thus, there is no need for a class_init at the perl level.  you can consider
the loading of your module to be class_init (your module gets parsed and
executed once, which is when the registration happens).


base_init, on the other hand, gets called once during the initialization of
each subclass.  i can see how this might be important for some GTypes, etc,
and i can think of some interesting tricks to pull with it, so it's not
something to say "ah, we don't need that."

at first glance, my proposal would be to have perl call INIT_BASE as it calls
INIT_INSTANCE and friends.[2]  however, this is not as easy as it sounds, for
one simple reason: you don't get to associate callback data with the base_init
function.

when you get into base_init(), you have a void pointer, which is an arbitrary
class structure.  when we do G_TYPE_FROM_CLASS on this pointer, we get the
gtype of the type being created --- *not* the gtype of the one whose base we
are initializing!  if we could associate some user data with that function
pointer, we'd have no problems, but, well, how the hell are we going to do
that?  i tried tacking some extra space onto the class structure and storing
information in there, but all i can ever get from G_TYPE_FROM_CLASS is the
bottommost type, not the one we need.  normal C code knows what type it's
base-init-ing by what function you've called, but we're going to be using the
same function for all perl-derived classed (unless somebody knows how to write
self-modifying C programs that don't get caught by noexec traps).

given that, problems like making sure your INIT_BASE method exists at the
right time, figuring out what to pass to the INIT_BASE method, and re-tooling
Glib::Type::register to create types other than GObject derivatives seem like
child's play.


that's not to say "no"...  just that i'm stuck.


Now, the biggest problem I see with this is that, since GType::register is
Perl-visible, the only thing you can really pass in is a CV... but, of
course, there's no typemap for GTypeClass (or it's "subclasses", like
GObjectClass), which is what the CV would be receiving, so there's a
question of how to marshal the arguments.  OTOH, if the code just got an
opaque SV containing a pointer to the structure, I'd be fine with that,

i'd rather not.  more likely i'll pass you a package name, and you can look up
the class structure from that package's associated GType.



[1] in retrospect, this was a silly limitation.  luckily, it won't be that
hard to rectify, although it may be slightly messy to document.  anyway...

[2] recall that perl's convention is to reserve all-caps subroutine names for
things that get called from within the bowels of perl rather that from your
own perl code, e.g. DESTROY, TIEHASH, STORESIZE, UNTIE, and gtk2-perl's
GET_PROPERTY, INIT_INSTANCE, and friends.   we've consciously swizzled the
names of instance_init and instance_finalize to be verb-noun (like TIEHASH,
but readable ;-), so base_init becomes INIT_BASE.


-- 
muppet <scott at asofyet dot org>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]