Create  Edit  FrontPage  Index  Search  Changes  History  RSS  Login

How to Implement Ruby-GNOME2

How to implement Ruby-GNOME2

This document explains how to implement an extension for Ruby-GNOME2.

Signals and Properties

Accessors methods (set/get) for properties are automatically generated. Signals are also directly handled by GLib::Instantiatable#signal_connect. So, you do not need to manually implement them anymore.

Deprecated/Obsolete classes/methods

Don't implement them.

Macros

You need to know that there are some macros which can help you to easily implement a new class/method. Almost all of these macros are in the header files glib/src/rbgobject.h, rbglib.h and gtk/src/rbgtk.h.

Define class/interface

These macros are used in Init_*() functions:

G_DEF_CLASS(gtype, name, module)
G_DEF_CLASS2(gtype, name, module, mark, free)
Define a class. If you want to define mark and free functions by yourself, use G_DEF_CLASS2. This returns a new ruby class value.
G_DEF_CLASS3(gtype_name, name, module)
Define a class dynamically. This is for private gtype classes such as GdkScreenX11, GdkWindowImplWin32. This returns nothing. These classes can't define the methods/constants by themselves. And these classes appear since a method which creates the private gtype has been called by ruby script.
G_DEF_INTERFACE(gtype, name, module)
G_DEF_INTERFACE2(gtype, name, module, mark, free)
Define a module. If you want to define mark and free functions by yourself, use G_DEF_INTERFACE2.
G_DEF_ERROR(domain_quark, name, module, parent, enum_type)
G_DEF_ERROR2(domain_quark, name, module, parent)
Define an error class which is called by RAISE_GERROR.
void rbgobj_boxed_not_copy_obj(GType gtype)
Use this method if the GBoxed object shouldn't be copied during its RVALUE conversion (for example in GBOXED2RVAL or G_INITIALIZE).

Initialize object

These macros are used in class constructors (methods initialize):

G_INITIALIZE(obj, cobj)
RBGTK_INITIALIZE(obj,gtkobj)
RBGST_INITIALIZE(obj,gstobj)
Initialize an object. If the class is a descendant of GtkObject, use RBGTK_INITIALIZE. If the class in a descendant of GstObject, use RBGST_INITIALIZE.

Convert Ruby <-> GLib/GTK

RVAL2GOBJ(obj)
GOBJ2RVAL(gobj)
VALUE(GLib::Object) <-> GObject
RVAL2BOXED(obj)
BOXED2RVAL(cobj, gtype)
VALUE(GLib::Boxed) <-> GBoxed
RVAL2GENUM(obj, gtype)
GENUM2RVAL(gobj, gtype)
VALUE(GLib::Enum) <-> GEnum
RVAL2GFLAGS(obj, gtype)
GFLAGS2RVAL(gobj, gtype)
VALUE(GLib::Flags) <-> GFlags
RVAL2CSTR(v)
CSTR2RVAL(s)
VALUE(String) <-> gchar*
CSTR2RVAL2(s)
Convert gchar* s to VALUE(String) and then call g_free(s).
RVAL2CBOOL(v)
CBOOL2RVAL(b)
VALUE(true or false) <-> gboolean
GVAL2RVAL(v)
GValue(GLib::Value?) -> RValue. RVAL2GVAL(v) is not yet prepared. If you want to convert RValue to GValue, then use rbgobj_rvalue_to_gvalue():
GValue gval = {0,};
g_value_init(&gval, RVAL2GTYPE(value));

rbgobj_rvalue_to_gvalue(value, &gval);
/* then use gval... */
GEV2RVAL(ev)
RVAL2GEV(ev)
VALUE(Gdk::Event) <-> GdkEvent
GLIST2ARY(list)
GSLIT2ARY(list)
GList/GSList of GObject -> Array
GLIST2ARY2(list)
GSLIT2ARY2(list)
GList/GSList of GBoxed -> Array
GLIST2ARYF(list)
GSLIST2ARYF(list)
GLIST2ARY2F(list)
GSLIST2ARY2F(list)
Ditto. But call g_list_free() or g_slist_free() internal.

Convert RGObjClassInfo <-> GType,Ruby class/instance

CLASS2CINFO(klass)
Class -> RGObjClassInfo
GTYPE2CINFO(gtype)
GType -> RGObjClassInfo
RVAL2CINFO(obj)
VALUE -> RGObjClassInfo

Convert GType <->Ruby class/instance

GTYPE2CLASS(gtype)
GType -> Class
CLASS2GTYPE(klass)
Class -> GType
RVAL2GTYPE(obj)
VALUE -> GType

Relatives

This saves an object from the GC. Usually obj is self and rel is child widget/object or proc object.

G_RELATIVE(self, rel)
Make a relation. Use this with proc object.
G_RELATIVE2(self, rel, id, hash_key)
Make a removable relation.
G_REMOVE_RELATIVE(self, id, hash_key)
Remove a relation.
G_CHILD_SET(self, id, child)
Sets child to self with id(rb_intern value).
G_CHILD_UNSET(self, id)
Unsets the child value of the id.
G_CHILD_ADD(self, child)
Adds a child to self. This is equivalent with G_RELATIVE(self, child), but the name is obviously.
G_CHILD_REMOVE(self, child)
Remove child from self.

Setter methods

G_DEF_SETTER(klass, name)
G_DEF_SETTERS(klass)
These macros can be used to implement automatically setters methods with operator =. You implement by yourself the method set_hoge(aValue), and then you call G_DEF_SETTER(klass, "hoge").
set_hoge(a)          #return self (implemented by yourself)
hoge=(a)             #return a    (created automatically from set_hoge)

If you have several set methods in a single class, then you can call G_DEF_SETTERS which will do the magic for all of them.

Define constants

G_DEF_CONSTANTS(mod, type, strip_prefix)
Define constants of Module/Class from GType. G_DEF_CONSTANTS is used with G_DEF_CLASS. Here is a practical example from Gtk::Window source code:
/* Define Gtk::Window::TOPLEVEL and Gtk::Window::POPUP. */
G_DEF_CLASS(GTK_TYPE_WINDOW_TYPE, "Type", gWindow);
G_DEF_CONSTANTS(gWindow, GTK_TYPE_WINDOW_TYPE, "GTK_WINDOW_");
G_RENAME_CONSTANT(orig, alt)
Rename constants which has been defined with G_DEF_CONSTANTS().
G_RENAME_NICK(orig, alt)
Rename nick of GEnum/GFlags which start numerical character. Ruby/GLib define the methods of GFlags from nick automatically. If nick starts numerical character, it causes a syntax error.

Block

G_BLOCK_PROC()
This macro calls either rb_f_lambda() (Ruby <= 1.7.x) or rb_block_proc() (Ruby >= 1.8.x). You shouldn't use rb_f_lambda() or rb_block_proc() directly, if you want to produce portable code.

Argument of properties as hash

G_SET_PROPERTIES(self, properties)
This macro will help you to implement set_hoge(a, {:foo => 0, :bar =>"hoge"}) for properties.

Symbol properties

G_SET_SYMBOL_PROPERTY(gtype, name)
Define this in Init_*() for properties which use Symbol instead of String (e.g. Gtk::Stock).

Implement class which does not conform to GType system (no G*_TYPE_* macros)

You can either use traditional method, or implement the class as a GBoxed object.

Here is an example for the class Foo:

  1. Create the following function, which will return a GLib type for our class:

    GType foo_get_type(void) {
        static GType our_type = 0;
        if (our_type == 0) {
            our_type = g_boxed_type_register_static("Foo",
                                                    (GBoxedCopyFunc)foo_copy,
                                                    (GBoxedFreeFunc)g_free);
        }
        return our_type;
    }

    If Foo has foo_ref/foo_unref, then use them instead of foo_copy, g_free.

  2. Create the following function, which will return a copy of an objet from our class:

    Foo* foo_copy(const Foo* foo) {
        Foo* new_foo;
        g_return_val_if_fail (foo != NULL, NULL);
        new_foo = g_new(Foo, sizeof(Foo));
        *new_foo = *foo;
        return new_foo;
    }

    Rarely, there are some objects which shouldn't make copy and shouldn't free them, you may need to write it as follows:

    Foo* foo_copy(const Foo* foo) {
        return (Foo*)foo;
    }
    void foo_free(gpointer foo) {
        /* do nothing */
    }
    GType foo_get_type(void) {
        static GType our_type = 0;
        if (our_type == 0) {
            our_type = g_boxed_type_register_static("Foo",
                                                    (GBoxedCopyFunc)foo_copy,
                                                    (GBoxedFreeFunc)foo_free);
        }
        return our_type;
    }

    Furthermore, some objects may need to do g_free() there in this case.

  3. Define a G*_TYPE_* macro:

    #define G_TYPE_FOO         (foo_get_type())
  4. You can now call in your Init_*() function:

    void Init_foo(void) {
        VALUE cFoo = G_DEF_CLASS(G_TYPE_FOO, "Foo", aModule);
        /* ... */
    }
  5. And for conversions:

    /* Ruby -> GLib */
    RVAL2BOXED(objet, G_TYPE_FOO);
    
    /* GLib -> Ruby */
    BOXED2RVAL(objet, G_TYPE_FOO))

GError handling

RAISE_GERROR(GError* error)
This macro will throw a Ruby exception according to the error code.

GLib::Object#signal_connect's block variables set manually

G_DEF_SIGNAL_FUNC(klass, signal_name, signal_g2r_func);
signal_g2r_func(guint num, const GValue* values);
You can define with these macros block variables for signals by yourself. These macros should be used only in special case (since signals are automatically handled).

Log handling from ruby scripts.

GLib::Log.set_error_domain(domain)
This function improve log handling. See glib/src/lib/glib2.rb.

Recommended editors

If you develop Ruby-GNOME2 with GNU Emacs, I recommend you to use ruby-style.el. To use ruby-style.el, you need to customize your ~/.emacs file as follows:

(add-to-list 'load-path "/path/to/ruby-style-el/directory")
(require 'ruby-style)
Last modified:2011/06/05 22:50:04
Keyword(s):
References:[FrontPage]