From: Thomas M. <ku...@ro...> - 2016-07-24 10:25:19
|
Am 24.07.2016 um 05:00 schrieb Kouhei Sutou: > Hi, > > In <453...@ro...> > "Re: [ruby-gnome2-devel-en] How-To Interfaces" on Sat, 23 Jul 2016 17:16:33 +0200, > Thomas Martitz <ku...@ro...> wrote: > >>> Ruby-GNOME2 doesn't support implementing interface in >>> Ruby. Because it needs interface specific C code. >>> >> What do you mean with interface specific c code? From my >> current observations it should be possible to extend rbg >> (seems to be the general shorthand for ruby-gnome2 in the >> code so I'll use that) such that you can create classes >> (inheriting gobject) that implement gobject interfaces >> purely in ruby. > Do you know how to implement GObject interface in C? > > Here are codes that GtkSizeGroup implements GtkBuildable: > > https://git.gnome.org/browse/gtk+/tree/gtk/gtksizegroup.c#n150 > https://git.gnome.org/browse/gtk+/tree/gtk/gtksizegroup.c#n273 > > You need to assign pointers of GObject interface functions > like: > > iface->custom_tag_start = gtk_size_group_buildable_custom_tag_start; > iface->custom_finished = gtk_size_group_buildable_custom_finished; > > https://git.gnome.org/browse/gtk+/tree/gtk/gtksizegroup.c#n276 > > The function type is GObject interface specific. So we need > to create function for each GObject interface functions. > > How did you implement GObject interfaces purely in Ruby? I see what you mean. Actually libffi provides that ability. You can use ffi closures to dynamically create trampoline (trampoline == closure) functions which call a generic ffi callback. The ffi callback is passed enough information to resolve which interface method to call (how the ffi callback receives the parameters from the trampoline is managed by libffi). The ffi callback also receives the paramters that the trampoline in order to link the method call to the actual GObjecet instance. The gobject-introspection library even has a helper function for that: g_callable_info_prepare_closure(). This receives a GICallableInfo and creates such a trampoline function. You also pass it an ffi callback which would (in our case) dispatch the method call into Ruby space (using rb_funcall or whatever). I have prototyped what I mentioned above, see http://pastebin.geany.org/A26m9/. The printfs eventually print "closure for TestPlugin::activate called" for a my test ruby class which includes the Peas::Activatable module. rbg uses libffi already in another place, and it comes automatically via glib dependency. > >> pygobject can do it after all. > Could you show us how PyGObject do it? pygobject does what I described above, it starts here: https://git.gnome.org/browse/pygobject/tree/gi/gimodule.c#n459 _pygi_make_native_closure() makes g_callable_info_prepare_closure() call based on GI information and then sets the function pointer to that trampoline function (*method_ptr = closure->closure) > >> That's clear. Before I implement a loader I need rbg to >> meet the requirements for libpeas. That's mainly >> supporting interfaces. The libpeas loader would look for >> ruby classes that implement certain interfaces, and >> instantiate them. > You can use Ruby-GNOME2 when you implement the Ruby loader. That's my plan. > >> PS: I'm currently having a problem with "rgbobjects" being >> initialized twice if I call g_type_interface_static() for >> it > g_type_register_static()? > I don't know about the details of what you're doing but you > should not call XXX_static() dynamically. I believe the _dynamic functions are meant to be used with GTypePlugins. I don't think rbg uses this mechanism (GLib::Object.type_register/rbgobj_register_type uses g_type_register_static). pygobject doesn't do either and also uses _static variants. You can use the static variants if you don't plan to recycle GType values IIUC. Best regards. |