GObject

GObject(ジーオブジェクト)は、GLib Object Systemの略称で、移植性の高いオブジェクトシステムと言語間の透過的な相互運用性を提供するフリーソフトウェアのライブラリです。LGPLライセンスで提供されています。

歴史



GObjectはC言語で実装されており、他の言語ではバインディングを通して利用可能です。GLibとlibcにのみ依存しており、GNOMEの基盤として広く利用されています。例えば、GTK、Pango、Accessibility Toolkitなど、多くのGNOMEライブラリやアプリケーションがGObjectを利用しています。

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

GLibとの関係



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

型システム



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

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

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

基本型



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

GLib 2.9.2では、non-classedの基本型は以下の通りです。

  • - 空の型 (G_TYPE_NONE): C言語のvoidに対応
  • - C言語のchar、int、long、64ビット整数に対応した型 (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)
  • - 列挙型とフラグ型 (G_TYPE_ENUM, G_TYPE_FLAGS): C言語のenumに対応
  • - IEEE 754の単精度および倍精度の浮動小数点数 (G_TYPE_FLOAT, G_TYPE_DOUBLE): C言語のfloatとdoubleに対応
  • - 文字列型 (G_TYPE_STRING): C言語のchar に対応
  • - 不透明ポインタ型 (G_TYPE_POINTER): C言語のvoid に対応

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

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

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

派生型



GObjectの組み込みの基本型から派生する型は、以下の4種類に分類されます。

1. 列挙型とフラグ型
オブジェクトシステムとの関連で使用される列挙型や整数ベースのビットフィールド型です。例えば、オブジェクトのプロパティの型などに使われます。これらの型の登録を行う初期化コードは、通常、glib-mkenumsツールで自動生成され、別ファイルに格納されます。

2. ボックス化型
完全なクラス型にするには単純すぎるデータ構造で、型システムに登録する必要があるものです。例えば、あるクラスにbackground-colorというプロパティを追加する場合、その値はstruct color { int r, g, b; }のようなデータ構造のインスタンスであるとします。これをGObjectのサブクラスにしたくない場合、ボックス化型で表し、コピーや解放などの機能を提供できます。GObjectには、GLibの単純なデータ型を包んだ各種ボックス化型が最初から備わっています。ボックス化型は、外部オブジェクトのタグ付きコンテナとしても使用できます。

3. 不透明ポインタ型
コピーや解放などの機能が不要で、ボックス化型では大げさすぎるオブジェクトを扱うために使用します。これらのオブジェクトは、単に不透明ポインタ (G_TYPE_POINTER) として扱っても良いのですが、派生ポインタ型を生成することで、特定用途のオブジェクトであることを示すことができます。

4. クラス型とインタフェース型
GObjectアプリケーションにおける大半の型はクラス型であり、通常のオブジェクト指向的な感覚で言うと、rootクラスであるGObjectから直接または間接的に派生します。Java風のインタフェースもありますが、2006年現在ではあまり使用されていません。GIMPはGObjectのインタフェース型を使用しています。

メッセージング・システム



GObjectのメッセージングシステムは、closureとsignalという2つの要素から構成されます。

  • - Closure
コールバックを一般化したもので、C言語C++以外の言語からも使用できます。例えば、PythonJavaのコードをClosureの機構を通してGObjectから呼び出すことができます。

  • - Signal
Closureを呼び出すための主要なメカニズムです。オブジェクトは、特定のSignalとClosureのマッピングを指定したSignalリスナーを登録します。登録されたSignalが発信されると、対応するClosureが呼び出されます。GTKでは、すべてのネイティブGUIイベント(マウスの動きやキーボード操作)がGObjectのSignalを発信し、対応するリスナーがそれに対して動作します。

クラス実装



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

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

  • - インスタンス構造体
オブジェクトのインスタンスごとに存在し、先頭にスーパークラスのインスタンス構造体があります。その後、インスタンス固有の変数群が続きます。C++のメンバ変数に対応します。C言語の構造体にはアクセス修飾がないため、インスタンス構造体にはプライベートデータへのポインタ_privがあります。プライベート構造体は共通ヘッダファイルで宣言できますが、定義は個々の実装ファイルでのみ行われ、外部からは見えません。プライベート構造体をGTypeに登録すると、自動的にオブジェクトシステムで確保されます。プライベートデータが必要な場合は、常にG_TYPE_INSTANCE_GET_PRIVATEを使用すれば、_privポインタを構造体に含める必要はありません。

GObjectフレームワークの欠点



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言語でもオブジェクト指向的なコーディングが可能になります。

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

他のオブジェクトシステムとの比較



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

もう1つの重要な違いは、C++Objective-Cが独立した言語であるのに対して、GObjectは単なるライブラリであり、新しい構文やコンパイラ機能を追加しているわけではないという点です。例えば、GObjectベースのコードを書く際には、明示的なキャストが頻繁に必要になります。したがって、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よりもカプセル化とコードの再利用という面で優れています。

出典



The GObject Reference Manual (and tutorial)
GObject Tutorial Aug 2004
GOB2 — the GObject Builder
Vala'>Vala Homepage

もう一度検索

【記事の利用について】

タイトルと記事文章は、記事のあるページにリンクを張っていただければ、無料で利用できます。
※画像は、利用できませんのでご注意ください。

【リンクついて】

リンクフリーです。