[Geany-devel] GObject, new plugin interface ....

Matthew Brush mbrush at xxxxx
Thu Mar 17 06:56:05 UTC 2011

On 03/16/11 22:25, Lex Trotman wrote:
> Hi Matthew and All,
> @Matthew, I've looked at your dbus repo.  I might not have understood
> how you were relating it to this, but to me it looks like you are just
> using the old plugin interface, rather than anything to do with a new
> interface.

It's very bare still, but there are some things going on which fall into 
line with the GObject interface.  The only real reason it's been
referred to is that it 1) provides a GObject wrapper/C API around the 
current plugin API emitting signals from the right objects, using real 
properties, etc, 2) (will) provide a shared library that 
bindings/clients can link to, and 3) provides process isolation.  Other 
than those ideas it's so incomplete/new as to not be too relevant.  I'm 
actually not really planning on working on it until after there's a new 
GObject interface to Geany, since afterwards, it would be just a matter 
of inheriting from a few classes and tacking on GDBus stuff.

Unfortunately, there is some context around this which has been 
discussed around the geany-vala-binding, that a lot of which wasn't on a 
ML.  It's very easy to summarize some of the ideas I've had/heard so far:

   - The geany-vala-binding should be sort of a "raw" wrapper around
     the existing plugin API, providing simple access from Vala code.

   - There needs to be a GObject wrapper around a lot of the
     existing stuff where it makes sense, since a lot of it is
     sorta OOP in design.  This could use Vala to generate all of
     necessary boiler-plate GObject C code and allow doing things
     like ABCs and interfaces without gobs of (hand-written) code.

   - Signals for the plugins need to be emitted from the
     appropriate objects. rather than the current central
     GeanyGObject which is has all the signals.  An example would
     be that the "saved" signal should be on a Document object.

   - The API should enforce read/write access on the objects
     via properties/accessors.  The current API just exposes raw
     struct members, certain ones which, when set would result
     in strange behaviour in Geany.  The current API does have some
     getters/and setters though they aren't really consistent.  For
     an example of how the Vala binding is wrapping this
     inconsistent access, see [1].  The point of the DBus binding
     directly wrapping the Vala binding was to make it a true
     GObject API, where the Vala binding just provides a window to
     the existing raw C code (more or less).

   - Libpeas[2] should be used as the actual plugin finder/loader.  It's
     a GObject/GLib library designed specifically for finding plugins
     in different languages, loading their interpreter, and doing
     stuff like activation/deactivation.  It seems Gedit is using this
     as well as several other popular GNOME-ish programs.

   - There is a huge namespace clash with the current plugin API, in
     order to use sensible prefixes and class names.  Nothing in the
     new interface can be prefixed with Geany, geany or GEANY, which
     of course would be the sensible prefix for an API.  The new
     interface would have to use something like GeanyLib or LibGeany
     or whatever, and then in the language bindings the namespace
     could be whatever (except in Vala where there will still be

I think that roughly sums up the discussion I've heard so far that may 
or may not have been on this ML.

Why all the discussion around Vala[3]?  It's just *really* nice for 
generating GObject C APIs, like GOB2 on steroids.  It can output C files 
so that users are not require to have the valac compiler installed, it 
also can output C header that can be installed like headers are with any 
other library for use by C code.  My personal opinion is that it would 
be ideal to use Vala for the new GObject interface, at the very least to 
get something working, and then possibly port it bit by bit into 
hand-crafted C (though valac's C is pretty clean considering).

> @All,
> Having reviewed what has been said in the thread to date, there is no
> real substance, so I think its likely that we may be talking about
> subtly different things.  So to start the ball rolling here is an
> initial description of what I understand as the aims of this work and
> how I see it possibly being implemented.
> As I see it the purpose is to define a new plugin interface to Geany
> that exposes all the required machinery through a set of GObjects
> which can be (semi) automatically interfaced to languages other than
> C, allowing Geany to have plugins written in multiple languages.

Using GObject-introspection hopefully in most places[4].

> This new interface should provide at least the capabilities of the
> current plugin interface.


> The way I see it being implemented, is not to change Geany's existing
> C structures into GObjects, rather, that the GObjects provide an
> interface to the existing C implementation and may not even map one to
> one with the existing structures.

This is in line with the previous discussions, especially the 
geany-vala-binding providing Vala access for the GObject wrappers to 
use.  I agree that in quite a few cases it won't (or shouldn't) map 1:1 
with the old API.

> This has several advantages,
> 1. the interface is somewhat isolated from the Geany implementation,
> allowing the implementation to evolve without causing a change in the
> interface seen by plugins.  The current plugin interface is so thin
> that it is easy for changes to Geany to affect the interface.
> 2. the impact on the core implementation is minimised, so the impact
> on anything else happening in Geany itself is smaller.
> 3. The interface can be defined such that it is easy for plugins to
> use, independent of the underlying implementation

I studied the code in documents.{c,h} a bit just to see what it would 
take to convert a GeanyDocument into a GObject.  My observations were 
that it would a) require an almost complete re-write of that code, b) 
completely mess with the existing plugin API as well as tons of stuff in 
the core that uses GeanyDocument's and c) that it would bloat the code 
up so much that I don't think it would fit with Geany's "fast and light" 
philosophy.  So your #2 point is really important I think.

> I see the GObjects as simply containing pointers to one or more of the
> Geany structures and the methods each being just a few calls to
> existing functions that operate on these structures.

Yep, and wrapping them up in GObject properties and signals so Gobject 
introspection can do its magic in making the higher level language 
bindings idiomatic (or I guess OOP-ish, since it's roughly the same in 
most languages I know).

> There will still need to be code added to the existing implementation
> since it needs to create and destroy the GObjects as required and will
> have to emit signals on them when required.  But this is a much less

My initial though was a regular old Geany plugin, using the Vala binding 
and Vala output C API to provide the "glue" without even touching the 
existing core code directly.  This would at least provide a nice 
testbed.  Then the existing plugin API could just have the odd struct 
tweaked or function added, etc.

> intrusive change compared to re-implementing core in GObjects.  In
> fact it should be only additional code (albeit intertwined in the
> existing source), so minimising the likelihood of bugs being
> introduced into the existing Geany functionality.

Very important indeed.

> Since the purpose is to support multiple languages, I think that some
> support for initialising and sharing interpretors/runtimes also needs
> to be created.  It doesn't help someone to write Python or C# plugins
> if they have to figure out how to interface the Python interpretor or
> Mono runtime first.  That should be done once for each language and be
> a loadable part of Geany.  This process should also know how to find
> the plugins in the particular language, like Java ones in jar files,
> Python ones in directories with __init__.py in them etc.  Sharing is
> needed to reduce the bloat that would occur if each plugin had to have
> a copy of the interpretor/runtime code

This is exactly where LibPeas[2] fits in.  I've not found anything that 
would fit the bill as well as LibPeas would.  Also, if we were to add 
interpreter/runtime loaders to LibPeas, the benefits would populate 
across to other important projects like Totem, Gedit, Eog, etc. and of 
course vice versa.  Currently LibPeas only has plugin loaders for C (so 
probably Vala and Genie as well), Python and JS, but surely more can and 
will be added in the future.

> Hope this gives something to think about and throw things at.

Thanks for getting the ball rolling, I'm anxious to hear what others 
have to say.

[2] http://library.gnome.org/devel/libpeas/0.7/
[3] http://live.gnome.org/Vala/Tutorial
[4] http://live.gnome.org/GObjectIntrospection

Matthew Brush

More information about the Devel mailing list