ruby-****@sourc*****
ruby-****@sourc*****
2004年 2月 23日 (月) 02:16:09 JST
------------------------- REMOTE_ADDR = 218.231.161.247 REMOTE_HOST = URL = http://ruby-gnome2.sourceforge.jp/?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 of those 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 dynamicaly. This is for private gtype classes such as GdkScreenX11, GdkWindowImplWin32. - This returns nothing. These classes can't define the methods/constants by themselves. + 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. --- 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 --- RVAL2CSTR(v) --- CSTR2RVAL(s) VALUE(String) <-> gchar* --- 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(Gtk::Event) <-> GtkEvent --- GLIST2ARY(list) --- GSLIT2ARY(list) GList/GSList of GObject -> Array --- GLIST2ARY2(list) --- GSLIT2ARY2(list) GList/GSList of GBoxed -> Array === 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(obj, rel) Make a relation. --- G_RELATIVE2(obj, rel, id, hash_key) Make a removable relation. --- G_REMOVE_RELATIVE(obj, id, hash_key) Remove a relation. === 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). === Recommended editors If you develop Ruby-GNOME2 with GNU Emacs, I recommend you to customize your ~/.emacs file as follows: (c-add-style "ruby" '("bsd" (c-basic-offset . 4) (c-offsets-alist (case-label . 2) (label . 2) (statement-case-open . 2) (statement-case-intro . 2)))) (add-hook 'c-mode-common-hook '(lambda () (setq indent-tabs-mode nil))) - ((<Masao>))