Re: signals versus vfuncs



Christof Petig said:
> Perhaps widget derivation on the fly (take a base widget and override
> just some vfuncs without adding member variables (extending the instance
> struct)) should deserve an API ???
>
> e.g.
>    GType modify_type(GType base, const char *new_type_s_name, <list of
> vfuncs and implementations>);
>    void gobject_change_type(GObject *, GType new_type);

i've tried coming up with something like this, as a custom wrapper for my
bindings to use.  it's not easy, and it doesn't seem useful in practice. 
overriding existing vfuncs means you have to have the struct offsets
someplace, and you have to know how to marshall them.  with all that, you
either need a database of vfuncs and parameter types, or custom code all over
the place, which means the modifier functions are pointless.  rather than use
the database (which would be runtime overhead), i've chosen the code route
(maintenance overhead, but faster at runtime).


>> we can't just call a method named "do_something" because we'd get an
>> infinite loop.
>
> If I understand correctly that's just the problem that explicit
> namespace decoration
>
> void Derived::some_vfunc()
> {  ...
>     Gtk::Base::some_vfunc();
> }
>
> solves in C++.

unfortunately, that trick doesn't work in Perl.  when called from C (e.g. deep
within gtk+), the function in the derived class will never get called --- only
when it is called from perl code.  e.g.:

  # THIS CODE DOESN"T WORK
  package MyRenderer;
  our @ISA = qw(Gtk2::CellRendererText);
  sub render {
      print "hi!\n";  # do custom stuff, like draw a special background
      SUPER::render @_; # chain to parent to do normal text drawing
  }

will override render when called from perl, but will not be seen when the
renderer is used in a TreeView.  instead, you need to do something like this:

  package MyRenderer;
  use Glib::Object::Subclass 'Gtk2::CellRendererText';
  # special Gtk2::CellRenderer method which installs in the object class
  # special vfuncs that marshal to perl methods:
  __PACKAGE__->install_overrides;
  # this gets called by the vfunc installed above:
  sub on_render {
      # do custom stuff
      $self->parent_render (@_);
          # yet another custom way to call the parent's implementation,
          # because the public method accessible to SUPER would wind up
          # marshalling this function again.  comparable to
          # g_signal_chain_from_overridden().
  }


as you see, it's not impossible, it's just heinously ugly.


on a side note, for GInterfaces things are different; still painful to bind,
but not so painful to use, because we don't need a hack in place of SUPER.

-- 
muppet <scott at asofyet dot org>



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