gtksourceview2: implement completion provider

2019-07-03 02:45发布

问题:

The documentation states about SourceCompletionProvider:

You must implement this interface to provide proposals to SourceCompletion

What does "implement this interface" means in the context?

Should I create new GObject using this functions? Any example?.

When I have new GObject, then how can I add functions (like sourceCompletionProviderGetName) to it?

Thanks

回答1:

gtk+ is written in C, however it uses glib to provide an object-oriented style interface. Much of the gtk+ API is defined using interfaces in the OO sense. The actual gtk+ functionality is provided by "objects" (pointers to structs that follow the glib conventions) that implement those interfaces. So "implement this interface" means exactly that - write a "class" (in C via the glib system) that implements the desired interface (which you do by setting up the proper glib hooks to handle a specific function calls).

In gtk2hs, glib interfaces are translated as type classes with the word "class" appended to the end. SourceCompletionProviderClass is one of these classes, and is meant to exactly represent the glib interface. Unfortunately, the C-side "class methods" aren't really exposed in Haskell. The only method the type class provides is a casting operation, and that is only to work around a mismatch between the Haskell type system and OOP inheritance trees. A glib-class-method is translated to a regular Haskell function operating on some data that can be casted to the appropriate type. This means that there's no good way to implement a new class instance via gtk2hs.

Although in theory you might be able to shoehorn the necessary behavior in from the Haskell side by creating a new GObject, it's highly likely that not all necessary functions (you'd need some low-level glib stuff) are exposed, so you'd need to bind them yourself (I seem to recall the gtk2hs maintainers posting something like this a year or two ago, but can't find the link now). At that point, it's probably less error-prone to implement it all in C yourself. I have a codebase that does this for the cellrenderer interface, which you might find useful as a model. Most of the interesting stuff happens in the C header file. You can still set Haskell functions to be called from the C side via a function pointer.

If you really want to try to do it entirely from Haskell, I would start by finding a fairly simple interface (like my cellrenderer function, or another SourceCompletionProvider) and running the header through the preprocesser to see what the glib macros translate to. Then you can see the necessary definitions for setting up a glib object. The most important functions are *_init, *_finalize, *_get_property, and *_set_property, although a few others are necessary also. The * is a placeholder for the name of your object. IIRC, most of the default functions are set up by the G_DEFINE_TYPE macro, which sets the name prefix also.