GObject

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動: 案内検索
GObject クラスの典型的な初期化コード。この例ではあるクラスに file-size というプロパティを追加している

GObjectGLib Object System)は、移植性の高いオブジェクトシステムと言語間の透過的相互運用性を提供するフリーライブラリLGPL)である。GObjectはC言語で実装されており、他の言語ではバインディングによって利用可能となっている。

歴史[編集]

GLiblibcにのみ依存しており、GNOMEの基礎として GTK+PangoAccessibility Toolkit、多くのGNOMEライブラリやアプリケーションなど広範囲に利用されている。GTK+ 2.0 以前は、GObject のコードは GTK+ の一部だった。ただし、当時は GObject とは呼ばれておらず、ベースクラスは GtkObject と呼ばれていた。

GTK+ 2.0 リリースの際に、オブジェクトシステムを汎用ユーティリティとすべく、別ライブラリとして分離した。その際にGUI関係でない GtkObject クラスの大部分は新たなベースクラスである GObject に移された。GTK+ 2.0 のリリースされた2002年3月11日以降、GOjbect は独立したライブラリとして存在し続け、現在ではGUI以外のCUIアプリケーションやサーバアプリケーションにも広く使われている。

GLib との関係[編集]

GObject のマニュアル等はGLibとは別にあり[1]ライブラリファイルとしても別になっているが、ソースコードは GLib のソースツリー内にあって、GLib と共に配布されている。このため、GObject のバージョン番号は GLib のものを使っており、GLib パッケージの一部とされることが多い(例えば、DebianではGObjectを libglib2.0 パッケージファミリに入れている)。

型システム[編集]

GObjectフレームワークの基盤として、汎用の動的型システム GType がある。GTypeシステムは全オブジェクトの実行時記述を保持し、各種言語バインディングを実現するグルーコードからそれを使うことができる。型システムは任意の単一継承クラス階層を扱え、同時にクラスでないデータ型も扱える(不透明ポインタ文字列、各種サイズの整数浮動小数点数など)。

GType は登録されている型に属する値のコピー、代入、破棄の方法を知っている。整数などの型ではこれらは自明だが、複雑なオブジェクトには参照カウントがあるものもあれば、(一部だが)参照カウントのないものもある。型システムが参照カウントのあるオブジェクトを「コピー」するとき、一般に単に参照カウントをインクリメントするだけである。しかし、参照カウントのないオブジェクト(例えば文字列)のコピーでは、メモリを確保して実際にコピーを生成する。

この基本機能を使って GValue が実装されている。これは汎用コンテナ型であり、型システムが把握している任意の型の値を保持できる。このようなコンテナは、全てのネイティブ値をそのような型タグコンテナに格納する動的型付け言語とやりとりする際に特に便利である。

基本型[編集]

クラスと関連のない型を non-classed と称する。そのような型と何らかの root クラスに対応した全ての型を総称して「基本型」と呼び、それ以外の型を「派生型」と呼ぶ。これらは比較的閉じた体系であり、一般ユーザーが独自の基本型を生成することはないものと想定されているが、生成は可能であり、GObject クラスに基づかないクラス階層を独自に作ることもできる。

GLib 2.9.2[2]では、non-classed の基本型は以下の通りである。

  • 空の型、C言語の void に対応。(G_TYPE_NONE)
  • C言語の charintlong64ビット整数に対応した型。(G_TYPE_CHAR, G_TYPE_UCHAR, G_TYPE_INT, G_TYPE_UINT, G_TYPE_LONG, G_TYPE_ULONG, G_TYPE_INT64, G_TYPE_UINT64)
  • ブーリアン型。(G_TYPE_BOOLEAN)
  • 列挙型とフラグ型。C言語の enum に対応するが、後者はビットフィールドにのみ使われる。(G_TYPE_ENUM, G_TYPE_FLAGS)
  • IEEE 754の単精度および倍精度の浮動小数点数。C言語の floatdouble に対応。(G_TYPE_FLOAT, G_TYPE_DOUBLE)
  • 文字列型。C言語の char * に対応。(G_TYPE_STRING)
  • 不透明ポインタ型。C言語の void * に対応。(G_TYPE_POINTER)

classed の基本型は以下の通りである。

  • 標準クラス継承ツリーのrootである GObject のインスタンスの基底クラス型。(G_TYPE_OBJECT)
  • 基底インタフェース型。標準インタフェース継承ツリーの root を表している。(G_TYPE_INTERFACE)
  • ボックス化用の型。単純な値オブジェクトや外部オブジェクトを参照カウント付きの「ボックス」で包むのに使われる。(G_TYPE_BOXED)
  • 「パラメータ記述オブジェクト(parameter specification object)」用の型。オブジェクトのプロパティのメタデータを記述するのに使われる。(G_TYPE_PARAM)

型システムによって自動的にインスタンス化できる型を instantiable と称する。そのような型の重要な特徴は、インスタンスの先頭数バイトに必ずその型に対応したクラス構造(一種の仮想関数テーブル)へのポインタが格納されている点である。このため、instantiable な型は必ずクラスと対応している。逆に non-classed な型(整数や文字列)は instantiable ではない。また、classed な型はインタフェース型などを除いて instantiable である。

派生型[編集]

GObject の組み込みの基本型から派生する型は4種類に分けられる。

列挙型とフラグ型
オブジェクトシステムとの関連で何らかの形で使われる列挙型や整数ベースのビットフィールド型(すなわち、全ての enum 型)。例えば、オブジェクトのプロパティの型など。一般にこれらの型の登録を行う初期化コードは glib-mkenums[3] というツールで自動生成され、別ファイルに格納される。
ボックス化型
完全なクラス型にするには単純すぎるデータ構造だが、型システムに登録する必要があるもの。例えば、あるクラスに background-color というプロパティを追加したいとする。その値は struct color { int r, g, b; } のようなデータ構造のインスタンスである。これを GObject のサブクラスにしたくない場合、ボックス化型で表し、コピーや解放といった機能を提供できる。GObject には GLib の単純なデータ型を包んだ各種ボックス化型が最初から備わっている。ボックス化型は、外部オブジェクトのタグ付きコンテナとしても使える。
不透明ポインタ型
場合によっては、コピーや解放といった機能も不要で、ボックス化型でも大げさすぎるというオブジェクトもある。そのようなオブジェクトは単に不透明ポインタ (G_TYPE_POINTER) として扱っても良いが、派生ポインタ型を生成することで、それがある特定用途のオブジェクトであることを示すことができる。
クラス型とインタフェース型
GObject アプリケーションにおける大半の型はクラス型であり、通常のオブジェクト指向的な感覚で言えば、root クラス GObject から直接または間接的に派生する。Java風のインタフェースもあるが、2006年現在ではあまり使用されていない(2004年3月16日にリリースされた GLib 2.4 あたりで導入された新機能であるため)。GIMP は GObject のインタフェース型を使っている。

メッセージング・システム[編集]

GObject のメッセージングシステムは、相補的な closuresignal から構成される。

Closure
コールバックを一般化したもの。C言語とC++以外にもバインディングがある言語から使える。例えば、Python や Java のコードを Closure の機構で GObject から呼び出すことができる。
Signal
Closure を呼び出す一次機構。オブジェクトは、ある Signal と Closure のマッピングを指定した Signal リスナーを登録する。登録された Signal が発信されると、対応する Closure が呼び出される。GTK+ では、全てのネイティブGUIイベント(マウスの動きやキーボード操作)はGObjectのSignalを発信でき、対応するリスナーがそれに対して動作する。

クラス実装[編集]

GObject のクラスはクラス構造体とインスタンス構造体という少なくとも2つの構造体で実装される。

クラス構造体
C++ におけるvtableに相当する。先頭にスーパークラスのクラス構造体がある。その後に関数ポインタ群があり、それぞれがクラスの仮想メソッドを指している。クラス固有変数を使って、クラス変数をエミュレートできる。
インスタンス構造体
オブジェクトのインスタンス毎に存在する。先頭にスーパークラスのインスタンス構造体がある。その後にインスタンス固有の変数群があり、C++ のメンバ変数に対応する。

C言語の構造体には“public”、“protected”、“private”といったアクセス修飾がないので、インスタンス構造体にプライベートデータへのポインタ _priv がある。プライベート構造体は共通ヘッダファイルに宣言することはできるが、定義は個々の実装ファイルでのみ行われ、外部から見えないようにしている。プライベート構造体をGTypeに登録すると、自動的にオブジェクトシステムで確保される。プライベートデータが必要なとき常に G_TYPE_INSTANCE_GET_PRIVATE を使うようにすれば、_priv ポインタを構造体に含める必要はない。

GObjectフレームワークの欠点は、冗長性である。新たなクラスを生成するとき、型登録や各種マクロを多量にコーディングする必要があり、その多くは決まりきった形式である。GObject Builder や GOB2 はこの問題に対処するツールであり、Java風の構文からコードを生成できる。GOB2 で書かれたコードはコンパイル前にC言語のコードに展開される。他にもC#風の文法でコーディングできる Vala がある。

利用[編集]

C言語とGObjectを使っているフリーソフトウェアプロジェクトとしては、GNOMEデスクトップ、GTK+ツールキット、GIMP画像編集プログラムなどがある。

GObjectを使ったアプリケーションはC言語で書かれていることが多いが、GObject 自体はC++JavaRubyPython.NET/Monoなどのオブジェクトシステムともうまくマッピングできる。従って、GObjectフレームワークを使ったライブラリに言語バインディングを作るのは比較的簡単である。

しかし、C言語でGObjectのコードを書くのは若干大変である。特に高級オブジェクト指向言語に慣れたプログラマにとっては苦痛かもしれない。例えば、ちょっとしたサブクラスを書くだけで数百行のコードを必要とする。とはいうものの、GObject を使うことでC言語でオブジェクト指向的なコーディングが可能となる。

一級オブジェクトは存在しないが(GTypeにはメタタイプがない)、GObjectアプリケーションは実行時にクラスやインタフェースのようなメタオブジェクトを生成でき、イントロスペクションもサポートできる。この機能は言語バインディング以外にGladeなどのGUI設計アプリケーションで使われ、GObjectクラスを提供する共有ライブラリをロードし、そのクラスの全プロパティの一覧を獲得し、型情報とドキュメンテーション文字列を完成させるといったことが可能となる。

他のオブジェクトシステムとの比較[編集]

GObject はC言語での完全なオブジェクトシステムであり、C言語から派生したC++Objective-Cと同等のものと見ることもできる(ただし、C++ はオブジェクトシステム以外にも様々な機能がある)。C++ と GObject の明らかな違いは、GObject が多重継承をサポートしていない点である。

もう1つの重要な違いは、C++ や Objective-C が独立した言語であるのに対して、GObject は単なるライブラリであり、新たな構文やコンパイラ機能を追加しているわけではないという点である。例えば、GObjectベースのコードを書くとき、明示的な cast が頻繁に必要となる。従ってGObjectとC言語の組合せを通常のC言語とは別の言語と考えたとき、それはC++とは異なり、通常のC言語の厳密なスーパーセットとなっている。

C++コンパイラを対象とした標準ABIは存在しないので(例外としてWindowsではCOMがその役割を担っている)、あるC++コンパイラでコンパイルされたライブラリから、別のC++コンパイラでコンパイルされたライブラリを呼び出せないことがある。そのような互換性を必要とする場合、C++メソッドはC言語の関数としてエクスポートされる必要があり、C++のオブジェクトシステムが部分的に破綻する。原因の一部は、C++コンパイラがエクスポートするシンボルの一意性を保証するために、それぞれ独自に名前修飾しているためである。一方これとは対照的に、C言語にはオーバーロードも名前空間もないので、C言語ライブラリではエクスポートされるシンボルの一意性を保証するために明示的なプレフィックスを付けるのが一般的である。GObjectベースのライブラリはオブジェクト指向ではあるがC言語で書かれているので、コンパイラが何であっても明示的なシンボル名を使う。

おそらく最も意義のあるGObjectの特徴は Signal(他の言語ではイベントと呼ばれる)である。これは、GObject がGUIツールキット向けに開発されたために必要になった機能である。他のオブジェクト指向言語にも同様の機能はあるが、GObjectではオブジェクトシステムそのものに組み込まれている。このため、GObjectアプリケーションはSignalを多用する傾向があり、GObjectのコンポーネントは C++ や Java よりもカプセル化コードの再利用という面で優れている。

外部リンク[編集]