This site has been retired. For up to date information, see handbook.gnome.org or gitlab.gnome.org.


[Home] [TitleIndex] [WordIndex

GObject Consume - Qt/C++ binding generator

Motivation

The aim of GObject-Consume is generating C++ bindings for GObject based APIs on the fly, comparable to Javas "ws-consume" which generates stubs for SOAP webservices. Currently it supports Qt/C++ flavour - standard C++ is covered by gtkmm already. C++ in combination with Qt is very popular for developing GUIs, and GObject provides a good framework for writing platform infrastructure APIs. As it's no big deal to use C libraries in C++, an important goal is to make things more convenient, particularly garbage collection, containers and string types.

This project was inspired by Richard Dales blog (http://www.kdedevelopers.org/node/3878) about his Smoke-GObject project "Creating QMetaObjects from GObject Introspection data" and my previous attempt to hand-craft Qt/C++ bindings for GIO - which just seemed to be lots of boring work (but the experience definitely helped here).

Features

The Code-Generator

At the moment the code-generator generates two (huge) files go-out.h and go-out.cpp. Those files can be compiled with your application.

The following command will generate GTK bindings for certain GTK classes and functions, for instance:

go-consume -C Gtk::Window,Gtk::Button,Gtk::init,Gtk::main,Gtk::main_quit /home/me/sources

How it works

The Base classes

All the auto-generated wrapper classes for GObjects and GInterfaces inherit from GObjectReference:

class GObjectReference  // (simplified)
{
public:
    GObjectReference() : p(0) {}
    GObjectReference(const GObjectReference &other); // calls g_object_ref()
    ~GObjectReference(); // calls g_object_unref()
    // assignment - calls g_object_unref(old) and g_object_ref(copy):
    GObjectReference &operator=(const GObjectReference &other); 

    template <typename T>
    bool instanceOf();  // check if cast is possible (using GType runtime information)

    template <typename T>  // dynamic cast (using GType runtime information)
    T cast();

    bool isNull() const; // a null reference?

    // connect a GLib signal to a Qt slot:
    // The first time you call this method, it will 
    // attach a SignalHub (which derives from QObject) instance  
    // to the GObject 
    void connectSignal(const char * gSignal, QObject * obj, const char * qSlot);  

    void * p; // pointer to the encapsulated GObject

    ...
};

There are similar base-classes for structs and boxed types.

A simple example

Here is a simple example for reading a file with GIO:

File file = fileNewForUri(QString("http://l10n.kde.org/docs/doc-primer/docprimer.txt"));

Error err;
InputStream inputStream = file.read(Cancellable(), err);
if (inputStream.isNull())
{
        cout << "cannot open stream: " << err.getMessage() << endl;
        exit(1);
}

char buffer[READBUFSIZE];
while (int n = inputStream.read(buffer, READBUFSIZE-1, Cancellable(), err))
{
        buffer[n] = '\0';
        cout << buffer;
}

As you can see, the code almost looks like Java or C#, because the wrappers are "Value-types". Garbage collection happens automatically in the destructors of the stack-allocated wrappers.

Dynamic Casting

Because the inputSteam is actually a FileInputStream, you could cast it to the Seekable interface:

Seekable seekable = inputStream.cast<Seekable>();
seekable.seek(fileSize-20, SeekTypeSet, Cancellable(), err);

But you might want to check whether the cast is really possible:

if (inputStream.instanceOf<Seekable>()) { ... }

Signals

GObjectReference provides a method to connect GLib signals to Qt slots. Here is an example for connecting the GtKWindow "destroy" signal:

class MyApp : public QObject  {
        Q_OBJECT
public:
        MyApp() {}
        virtual ~MyApp() {}

public Q_SLOTS:
        void destroyWindow(const Gtk::Object& sender)
        {
                Gtk::mainQuit();
        }
};
...

MyApp app;

Window window = Window::newInstance(WindowTypeToplevel);
window.connectSignal("destroy", &app, SLOT(destroyWindow(Gtk::Object)));

Samples

The samples cover:

http://websvn.kde.org/trunk/playground/bindings/gobject-consume/samples/

Status

The project is still in pre-alpha stage, but many things like ref-counting, signals, casting, subclassing are already working. Still missing or sketchy:

Source-Code

svn co svn://anonsvn.kde.org/home/kde/trunk/playground/bindings/gobject-consume


2024-10-23 11:36