GNOME3用アプリケーション開発に入門してみる その2
GObject
GObject Reference Manual: GObject Reference Manual
C言語でオブジェクト指向を実現する仕組み。 他言語用にAPIを提供する仕組みも備えているので、 Cで書けばC++はもちろんPythonやPHPとかからも使えるようになる。 たぶん逆もしかり。
ざっと見ではC++のvtableとかマングル名とかをCの構造体や命名規則、 マクロで実装している感じで合っていると思う。 加えて参照カウンタやObserverパターンのためのsignalの規則もあるっぽい。
チュートリアルから開始。
ヘッダファイルはハイフンかアンダースコアで区切るのが一般的っぽい。 privateを末尾につけた場合はインストールしない。
とりあえず maman-bar.h
をコピペして、Object Construction, Object Destruction あたりまで進めてみる。
/* * Copyright/Licensing information. */ /* inclusion guard */ #ifndef __MAMAN_BAR_H__ #define __MAMAN_BAR_H__ #include <glib-object.h> /* * Potentially, include other headers on which this header depends. */ /* * Type macros. */ #define MAMAN_TYPE_BAR (maman_bar_get_type ()) #define MAMAN_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_BAR, MamanBar)) #define MAMAN_IS_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_BAR)) #define MAMAN_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_TYPE_BAR, MamanBarClass)) #define MAMAN_IS_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_TYPE_BAR)) #define MAMAN_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_TYPE_BAR, MamanBarClass)) typedef struct _MamanBar MamanBar; typedef struct _MamanBarClass MamanBarClass; typedef struct _MamanBarPrivate MamanBarPrivate; struct _MamanBar { /* Parent instance structure */ GObject parent_instance; /** Private data pointer */ MamanBarPrivate* priv; /* instance members */ }; struct _MamanBarClass { /* Parent class structure */ GObjectClass parent_class; /* class members */ }; /* used by MAMAN_TYPE_BAR */ GType maman_bar_get_type (void); /* * Method definitions. */ #endif /* __MAMAN_BAR_H__ */
/* * Copyright information */ #include "maman-bar.h" #include <glib.h> #include <glib/gprintf.h> /* If you use Pimpls, include the private structure * definition here. Some people create a maman-bar-private.h header * which is included by the maman-bar.c file and which contains the * definition for this private structure. */ struct _MamanBarPrivate { GObject *an_object; gchar *a_string; }; G_DEFINE_TYPE_WITH_PRIVATE (MamanBar, maman_bar, G_TYPE_OBJECT) static void maman_bar_dispose (GObject *gobject) { MamanBar *self = MAMAN_BAR (gobject); g_printf("maman_bar_dispose\n"); /* In dispose(), you are supposed to free all types referenced from this * object which might themselves hold a reference to self. Generally, * the most simple solution is to unref all members on which you own a * reference. */ /* dispose() might be called multiple times, so we must guard against * calling g_object_unref() on an invalid GObject by setting the member * NULL; g_clear_object() does this for us. */ // g_clear_object (&self->priv->an_object); /* Always chain up to the parent class; there is no need to check if * the parent class implements the dispose() virtual function: it is * always guaranteed to do so */ G_OBJECT_CLASS (maman_bar_parent_class)->dispose (gobject); } static void maman_bar_finalize (GObject *gobject) { MamanBar *self = MAMAN_BAR (gobject); g_printf("maman_bar_finalize\n"); g_free (self->priv->a_string); /* Always chain up to the parent class; as with dispose(), finalize() * is guaranteed to exist on the parent's class virtual function table */ G_OBJECT_CLASS (maman_bar_parent_class)->finalize (gobject); } static void maman_bar_class_init (MamanBarClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); g_printf("maman_bar_class_init\n"); gobject_class->dispose = maman_bar_dispose; gobject_class->finalize = maman_bar_finalize; } static void maman_bar_init (MamanBar *self) { self->priv = maman_bar_get_instance_private (self); g_printf("maman_bar_init\n"); self->priv->an_object = NULL; // g_object_new (MAMAN_TYPE_BAZ, NULL); self->priv->a_string = g_strdup ("Maman"); }
生成と破棄はたぶんこんな感じ。
#include "maman-bar.h" int main(int argc, char const* argv[]) { GObject* bar = g_object_new (MAMAN_TYPE_BAR, NULL); g_object_unref(bar); return 0; }
破棄がdisposeとfinalizeで分かれているのは参照カウンタがループしている時のためっぽい。