Design of Gir-FFI ↑

Basic Idea ↑

Gir-FFI uses FFI to read information from the GObject Introspection Repository. Based on that it creates bindings for the information read.

Class and method creation ↑

GirFFI::Builder creates classes and modules at runtime and adds appropriate method_missing methods to them to generate methods and perhaps other classes when required.

The following options were discarded, at least for now.

Method Naming ↑

Probably, get_x/set_x pairs should become x and x= to be more Ruby-like. This should be done either by defining them as such directly, or by aliasing. Blindly going by the name leads to weird results thoough, like having x, x= and x_full= as a set. Also, some get_ or set_ methods take extra arguments. These probably shouldn’t become accessors either.

Boolean-valued methods could get a ? at the end.

This requires a lot more thought. For now, the full method names as defined in the GIR are used.

Ruby-GNOME Compatibility ↑

Full Ruby-GNOME compatibility cannot be achieved automatically, since its object hierarchy differs from that of standard GObject: It puts Object in the GLib namespace, and defines signal_connect and friends as methods of GLib::Instantiable; In standard GObject they are functions.

Possibly, compatibility enhancing code can be added for these specific exceptions.

Reference Counting ↑

Because we can always make sure GObjects are unref’d when the Ruby object is GC’d, the mechanism of floating references actually gets in the way a bit. Therefore, when floating GObjects are constructed, GirFFI will sink them. All GObjects can then safely be unref’d using a Ruby finalizer. GObjects obtained through other mechanisms than with a constructor will be ref’d once when wrapping them in a ruby object.

Bootstrapping Class Design ↑

The interface to the GObject Introspection Repository itself is also introspectable. The interface is specified in terms of structs and functions rather than objects and methods. For now, the hard-coded Ruby bindings for this don’t follow the introspected specification: Gir-FFI cannot bootstrap itself.

Object initialization ↑

Each constructor method is implemented in Ruby by a pair of new/initialize methods. For example, a constructor new_from_file is implemented as a combination of the singleton method new_from_file and the instance method initialize_from_file. User-created subclasses override the appropriate initializer method and must call super with the appropriate arguments.

Here is an example of the generated pair of methods:

“‘ruby class Regress::TestObj def self.new_from_file(args) obj = allocate obj.__send__ :initialize_from_file, args obj end

def initialize_from_file(x) v1 = GirFFI::InPointer.from(:utf8, x) v2 = FFI::MemoryPointer.new(:pointer).write_pointer nil v3 = Regress::Lib.regress_test_obj_new_from_file v1, v2 GirFFI::ArgHelper.check_error(v2) store_pointer(_v3) end end