Search code examples
javascriptlinuxgobject

(GObjectIntrospection) Segmentation fault when trying to create ibus engine using javascript


GObjectIntrospection allows to use C object in any high level language. https://live.gnome.org/GObjectIntrospection

IBus is a input method framework for linux. code.google.com/p/ibus

I'm in bit of trouble using GObjectIntrospection / javascript. I tried to create an ibus engine. same code works in vala,python. but in javascript seg fault. I'm using opensuse 12.1 gnome3. "ibus-devel" package provides the /usr/share/gir-1.0/IBus-1.0.gir required for GObjectIntrospection.

I'm tring to run the following code.

#!/usr/bin/env gjs
const IBus = imports.gi.IBus;
//get the ibus bus
var bus = new IBus.Bus();
if(bus.is_connected()){
  var factory = new IBus.Factory({
  connection: bus.get_connection()
  });
   factory.add_engine({
   engine_name:"ibus-sarim",
   engine_type:typeof(this)
   });
}

It crashes on line 6, in "new IBus.Factory".

Terminal output,

(gjs:13353): GLib-GIO-CRITICAL **: g_dbus_connection_register_object:
assertion `object_path != NULL && g_variant_is_object_path
(object_path)' failed
Segmentation fault

I can't figure out where is the problem. I tried the vala test code provided with ibus at https://github.com/ibus/ibus/blob/master/bindings/vala/test/enchant.vala It compiles and runs fine. In enchant.vala line 148,

var factory = new Factory(bus.get_connection());

The code for creating Factory is same that i tried in javascript. also in python,

from gi.repository import IBus
from gi.repository import GLib
from gi.repository import GObject
IBus.init()
bus = IBus.Bus()
if bus.is_connected():
    factory = IBus.Factory.new(bus.get_connection())

This also seems to work fine, no seg fault. But in javascript it fails everytime. Any idea ? I'm banging on this for couple of days without any avail :(


Solution

  • In IBusFactory:

    "connection"               IBusConnection*       : Read / Write / Construct Only
    

    The documentation says "Construct Only". That's subject to interpretation for now, but it means to me that it is probably a private or protected class member. That said, the constructor is defined as:

    IBusFactory *       ibus_factory_new                    (IBusConnection *connection);
    

    There's that connection variable, in the constructor. Notice when you provide it exactly that way, your app works fine.

    const IBus = imports.gi.IBus;
    //get the ibus bus
    var bus = new IBus.Bus();
    if(bus.is_connected()){
        var factory = new IBus.Factory(bus.get_connection());
    }
    

    Now as for factory.add_engine(), the definition is here:

    void                ibus_factory_add_engine             (IBusFactory *factory,
                                                             const gchar *engine_name,
                                                             GType engine_type);
    

    That means you will have to provide the engine_name and engine_type as function parameters. This works:

    factory.add_engine('ibus-engine-name', some-engine-type);
    

    See http://ibus.googlecode.com/svn/docs/ibus/ch03.html for engine ideas. This code doesn't segfault, but it doesn't work either. It indicates the correct syntax up until add_engine()'s second parameter.

    #!/usr/bin/env gjs
    const IBus = imports.gi.IBus;
    //get the ibus bus
    var bus = new IBus.Bus();
    if(bus.is_connected()){
        var factory = new IBus.Factory(bus.get_connection());
        factory.add_engine("ibus-sarim", typeof(this));
    }