Bonobo简介
Bonobo是一个组件系统,它是GNOME实现可重用软件组件的基石。组件是指这样一种软件,它们提供了定义完善的接口,被设计来与其它的组件协同工作。在Bonobo体系中,CORBA是将组件们联系在一起的通信层。使用CORBA做底层的另外好处是,组件及使用组件的软件可以用任何语言编写而不影响它们的交互。Bonobo的诞生主要出于一下三个方面的原因:
Bonobo实现了一下功能:
Bonobo的目的是为Unix平台提供一套组件编写和符合文档的标准环境。GNOME只是其中的一个实现。与GTK+下对象命名习惯(如“GtkWindow”)不同,Bonobo对象使用CORBA repository ID的方式命名。如实现了Bonobo GNOME:ClientSite接口的对象可能的一个名字是“IDL:GNOME/ClientSite:1.0”。
Bonobo的组件分两大类:container和containee(又称为embeddable或components)。为了使得二者可以交互,Bonobo为它们定义了完备的接口IDL描述。从而实现实现Bonobo组件的核心就是是实现container/containee的标准接口。(其实container不一定是个component,但为简单起见,我们也这样称呼它。)
一个包容器必须实现接口:GNOME::ClientSite 和 GNOME::ViewFrame。如果要支持原地激活还要实现GNOME::UIHandler接口。一个组件则至少要实现接口:GNOME::Embeddable 和 GNOME::View接口。
其工作流程如下:
一个组件Embeddable只有一个ClientSite,每个显示View都需要一个ViewFrame。
Container和Containee的关系如下图:
图1:Container和Containee的关系
所有的Bonobo接口都是从GNOME::Unknown集成出来的。
module GNOME { interface Unknown { void ref (); void unref (); Object query_interface (in string repoid); }; };
好在GNOME已经替我们实现了这个接口,即GnomeObject:
typedef struct { POA_GNOME_Unknown servant_placeholder; gpointer gnome_object; } GnomeObjectServant; typedef struct _GnomeObjectPrivate GnomeObjectPrivate; typedef struct { GtkObject base; CORBA_Object corba_objref; gpointer servant; GnomeObjectPrivate *priv; } GnomeObject; typedef struct { GtkObjectClass parent_class; /* * signals. */ void (*query_interface) (GnomeObject *object, const char *repo_id, CORBA_Object *retval); void (*system_exception)(GnomeObject *object, CORBA_Object cobject, CORBA_Environment *ev); void (*object_gone) (GnomeObject *object, CORBA_Object cobject, CORBA_Environment *ev); } GnomeObjectClass; typedef struct { int ref_count; GList *objs; } GnomeAggregateObject; struct _GnomeObjectPrivate { GnomeAggregateObject *ao; int destroy_id; }; void gnome_object_ref (GnomeObject *object) { g_return_if_fail (object != NULL); g_return_if_fail (GNOME_IS_OBJECT (object)); g_return_if_fail (object->priv->ao->ref_count != 0); object->priv->ao->ref_count++; } void gnome_object_unref (GnomeObject *object) { g_return_if_fail (object != NULL); g_return_if_fail (GNOME_IS_OBJECT (object)); g_return_if_fail (object->priv->ao->ref_count > 0); object->priv->ao->ref_count--; if (object->priv->ao->ref_count == 0){ GnomeAggregateObject *ao = object->priv->ao; GList *l; for (l = ao->objs; l; l = l->next){ GnomeObject *o = l->data; gtk_signal_disconnect (GTK_OBJECT (o), o->priv->destroy_id); gtk_object_destroy (l->data); } g_list_free (ao->objs); g_free (ao); } } static void impl_GNOME_Unknown_ref (PortableServer_Servant servant, CORBA_Environment *ev) { GnomeObject *object; object = gnome_object_from_servant (servant); /* baaad !! we MUST call gnome_object_ref() */ object->priv->ao->ref_count++; } static void impl_GNOME_Unknown_unref (PortableServer_Servant servant, CORBA_Environment *ev) { GnomeObject *object; object = gnome_object_from_servant (servant); gnome_object_unref (object); }
所有Bonobo的接口都从GNOME::Unkown继承。类似地,GNOME替我们缺省实现了所有要求的接口,它们都是从GnomeObject继承。而我们甚至不需要懂CORBA和Bonobo就可以编写GNOME的组件程序。