Component Object Model (COM) とは
Component Object Model (COM、コンポーネント オブジェクト モデル) は、
マイクロソフトが提唱するソフトウェアの再利用を目的とした技術です。COMは、プラットフォームに依存せず、分散環境でも利用可能な
オブジェクト指向システムであり、相互に連携するバイナリソフトウェアコンポーネントを作成するために用いられます。
具体的には、
アプリケーションソフトウェア間の通信や、
オペレーティングシステムと
アプリケーションソフトウェアとのインターフェイス (API) として機能します。COMを利用して開発されたソフトウェア部品はCOMコンポーネントと呼ばれ、
C言語、
C++、
Visual Basic、Smalltalk、
Javaなど、多様な
プログラミング言語で開発可能です。
COMという用語は、OLE、OLEオートメーション、
ActiveX、COM+、DCOMなどを包括する総称としても使われます。COMコンポーネントは、他のソフトウェアと通信するためのインターフェースを持ち、
アプリケーションソフトウェア (COMクライアント) は、COMインターフェースを介してCOMコンポーネント (COM
サーバー) と通信します。これにより、ソフトウェア部品を組み合わせてサービスを提供できます。言語によるメモリ管理の違いは、参照カウントを利用し、オブジェクトの生成と破棄をそのオブジェクト自身の責任とする事で解決されます。また、異なるインターフェース間の型変換は、言語に依存しないQueryInterfaceメソッドで行います。
COMにおける最適な継承方法は、メソッド呼び出しを委譲する形でのサブオブジェクトの集合(アグリゲーション)を生成する方法です。
COMの仕様は公開されており、
XPCOMのような
クロスプラットフォーム実装も存在しますが、主に利用されているのは
Microsoft Windows環境です。MonoにおけるCOM相互運用もMS COMおよび
XPCOMを基盤としていますが、機能やサポート環境は限定的です。COMはOLEの後継として登場しましたが、現在では
.NET Frameworkに置き換えられる傾向にあります。しかし、
Microsoft DirectXのように、ネイティブ
C++での利用を前提としたパフォーマンス重視のAPIでは、依然としてCOMが利用されています。
COMはソフトウェアコンポーネントシステムとして、CORBAや
Java Beansと競合関係にあります。
COMの歴史
1991年、COMの前身であるOLEが、OLE 1としてWindows 3.1とともに公開されました。
1992年には、OLE 2が公開され、IUnknownインターフェースなど、後のCOMに繋がる要素が登場しました。
1994年、VBXコントロールの後継としてOCX (OLEコントロール) が登場し、OLEがコンポーネント技術を表す用語となりました。
1996年初頭、
マイクロソフトはOLEのうち、インターネットに関連する技術を
ActiveXと名称変更し、OLE技術が
ActiveXに統合され始めました。
1997年、
マイクロソフトはコンポーネントを利用するこれらの技術をComponent Object Modelと改称しました。
関連技術
COMはWindowsにおける主要なソフトウェア開発プラットフォームとして、数多くの技術の開発に影響を与えました。
COM+
WindowsのエンタープライズレベルOSとしての地位を確立するため、
マイクロソフトはWindows NT 4.0 Service Pack 4でMicrosoft Transaction Server (MTS) を導入しました。MTSは分散トランザクションをサポートし、メモリやスレッド管理を改善しました。
Windows 2000では、MTSをOSに統合し、COM+と改名しました。この時、
マイクロソフトはDCOMを独立要素として重視していませんでした。COM+は、トランザクショナルCOMコンポーネントを直接的に扱い、コンポーネントサービスアプリケーションインターフェースを通じて追加されました。
COM+は、コンポーネントをメモリからアンロードせずに再利用できる「コンポーネントファーム」で動作可能です。DCOMのみが可能だった分散化も可能となり、COM+イベントというイベントメカニズムや、MSMQを利用するQueued Componentsも提供されました。これにより、COM+プログラミングモデルでは、遅延バインディングイベントや、パブリッシャー/サブスクライバーモデルがサポートされました。
DCOM
DCOMは、ネットワーク経由でCOMコンポーネントを利用するための技術です。しかし、
.NET Frameworkの登場とともに、DCOMは利用される機会が減っています。
.NET
COMプラットフォームは、
.NET Frameworkに大幅に置き換えられ、
マイクロソフトは.NETに注力しています。COMは、高性能な
Visual BasicやASPで実装されたフロントエンドのコードと接続するために利用されていました。
.NETは、Windows FormsやWeb Formsに対してジャストインタイムコンパイル方式を提供し、C#、
Visual Basic .NET、
C++/CLIなど様々な言語でバックエンドコードを実装できます。しかし、DirectXなどのパフォーマンス重視のAPIでは、依然としてCOMが利用されています。
COMはまた、スクリプトからCOMオブジェクトを呼び出すためのインターフェースを提供し、
Microsoft Officeや
Internet Explorerのようなネイティブアプリケーションのスクリプト制御に利用されます。COMで使用されるGUIDシステムは、
マイクロソフトによるUUIDの実装であり、ユニークなIDが必要な場合に広く利用されています。
COM+が提供するトランザクションやコンポーネントキューは、エンタープライズ.NETアプリケーションでも重要です。
.NETは、COMとの相互運用性をサポートし、ランタイム呼び出し可能ラッパー(RCW)によってCOMオブジェクトを利用できます。また、COMクライアントは、COM呼び出し可能ラッパー(CCW)によって.NETオブジェクトを利用できます。
.NET Remotingは、オブジェクトがプロセスやマシンの境界を越えてリファレンスや値を透過的にマーシャリングできるようにし、COMのリモート実行の欠点を解決します。
Windowsランタイム
Windows 8およびWindows RTでは、Windowsランタイム(WinRT)が導入されました。WinRTはCOMを拡張したネイティブ技術ですが、Windowsメタデータ(WinMD)や言語プロジェクションにより、.NET言語や
JavaScriptからも利用可能です。
技術的詳細
COMコンポーネントはクラスID (CLSID) によって識別され、各COMコンポーネントは一つ以上のインターフェースを公開することで機能を提供します。インターフェースはインターフェースID (IID) で区別されます。CLSIDとIIDは、共にGUIDで構成されています。
COMインターフェースは
プログラミング言語とCOMを結びつけ、COMコンポーネントへのアクセスは全てインターフェースを通して行われます。これにより、プロセスやコンピュータを跨いでのアクセスが可能になります。
インターフェース
全てのCOMコンポーネントは、IUnknownインターフェースを継承する必要があります。IUnknownはAddRef、Release、QueryInterfaceの3つのメソッドを持ち、AddRefとReleaseは参照カウントを実装し、QueryInterfaceはインターフェースを取得するメソッドです。COMコンポーネントのインターフェースは、反射性、対称性、推移性を備えている必要があります。
インターフェースには、関数ポインタが並んだ仮想関数テーブルへのポインタが含まれています。
COMは、データストリームを管理するIStreamや、複合文書に利用されるIOleObjectなど、多くの標準インターフェースを定義しています。
コクラス
COMでは、クラスのことをコクラス (coclass) と呼びます。コクラスは、COMにおけるクラスを定義する言語非依存の方法です。1つのコクラスは、1つ以上のインターフェースの具体的な実装を提供します。
個々のコクラスは、クラスID (CLSID) またはProgIDで識別されます。クラスIDはGUIDを使った表現で、ProgIDは「プログラム名.コンポーネント.バージョン」という規則で表現される文字列です。
COMは、実装とインターフェースを切り離すという概念をもたらし、ポリモーフィズムの実現を可能にしました。これにより、1つのインターフェースに対して複数の実装を用意し、アプリケーション側が任意の実装を選択して操作できます。また、COMコンポーネントが要求するインターフェースをアプリケーション側で用意することで、コールバック処理などのカスタマイズも可能になります。
インターフェイス定義言語とタイプライブラリ
COMコンポーネントに関する情報の記述には、MIDL(
マイクロソフトインターフェイス定義言語)やタイプ
ライブラリが用いられます。MIDLはテキストファイルで主に開発時に利用され、タイプ
ライブラリは型に関する言語非依存の情報を提供するバイナリファイルです。
COMコンポーネントの開発は、IDLで型を定義することから始まり、IDLファイルはMIDLコンパイラで様々な
プログラミング言語向けにコンパイルされます。MIDLは、IDLファイルからタイプ
ライブラリ(.TLBファイル)も作成します。
タイプ
ライブラリは、コンパイラや実行環境で利用され、コクラスを特定の言語や環境で使用できるようにします。
オブジェクトフレームワークとしてのCOM
COMは
オブジェクト指向の哲学に基づいたプラットフォームで、
オブジェクト指向開発と実装を実現します。COMはランタイムフレームワークであり、型は明示的に識別可能で実行時に指定可能である必要があり、これを実現するためにGUIDが使われます。
COMはタイプ
ライブラリを提供し、オブジェクトの相互作用のための動的なフレームワークとして機能します。タイプ
ライブラリは、COMクライアントのコンパイル時や実行時に解釈され、オブジェクトがどのインターフェースをサポートするかを決定し、インターフェースメソッドを呼び出すために利用されます。
C++では、Windows API関数CoCreateInstance()を使用してCOMオブジェクトをインスタンス化できます。コクラスはCOMの世界では
オブジェクト指向のクラスであり、その主要機能は、バイナリの性質と、
プログラミング言語に非依存であることです。
COMのクラス、インターフェース、タイプ
ライブラリは、Windows
レジストリにGUIDのリストとして登録されます。COM
ライブラリは、各COMオブジェクトが正しいローカル
ライブラリを特定したり、リモートサービスのネットワーク上の位置を特定するために
レジストリを使用します。DLL
サーバー型のCOMコンポーネントはregsvr32で登録し、EXE
サーバー型のCOMコンポーネントは自身の起動引数で登録します。
レジストリに登録されたCOMコンポーネントは、コンピュータやネットワーク上の全てのCOMクライアントから共有されます。バージョンアップ時には、旧バージョンを登録解除し、新バージョンを登録し直すか、異なる名前とGUIDを持つインターフェースを定義する必要があります。
Windows XP以降では、マニフェストファイルを使用してコンポーネント依存関係を解決することも可能です。
参照カウント
IUnknownは、QueryInterface()による機能確認と、AddRef()およびRelease()を通じたオブジェクトの寿命管理をサポートします。COMオブジェクトは、参照カウントが0になった時にメモリを解放します。
AddRef()は参照カウントを増加させ、Release()は減少させます。一部の言語では自動参照カウントが提供されますが、
C言語では明示的な操作が必要です。
C++ではスマートポインタを利用することもできます。
COMは、参照を返す関数はAddRef()を呼び、インタフェースのポインタが上書きされる前にRelease()を呼び出すという原則があります。また、コピーを作る場合はAddRef()を呼び出す必要があります。
マイクロソフトは、
C++開発者向けにATLを提供し、スマートポインタオブジェクトによって参照カウントを自動管理できるようにしました。
インストール
COMは、クラスファクトリを使用してオブジェクトのインストールプロセスを標準化します。各COMクラスは、クラスID(GUID)とクラスファクトリに関連付けられている必要があります。クラスファクトリオブジェクトは、IClassFactoryまたはIClassFactory2インタフェースを持つオブジェクトであり、他のオブジェクトを生成する責任があります。
クラスファクトリは、一般的にCOMオブジェクトと同じ実行ファイル内に含まれています。クラスファクトリは、CoGetClassObject()で取得され、CreateInstance()メソッドでオブジェクトを生成します。COM
サーバーは、DLL
サーバーであればDllGetClassObject()をエクスポートし、EXE
サーバーであればCoRegisterClassObject()で登録する必要があります。
C++では、CoCreateInstance()で直接COMオブジェクトを生成できます。PowerBuilderのPowerScriptのような上位レベルのオブジェクト生成コンストラクタもあります。
リフレクション
COM初期の時代、オブジェクトの機能確認はQueryInterfaceメソッドに頼るしかありませんでした。その後、コンポーネントのCLSID、IID、メソッド解説などを含むCOMタイプ
ライブラリが導入されました。タイプ
ライブラリは、
Visual BasicやVisual StudioのようなRAD環境で利用されます。
プログラミング
COMは言語に依存しないバイナリ標準であり、タイプ
ライブラリを解釈できれば、どんな言語でも開発できます。ランタイム
ライブラリは、COMオブジェクトのインスタンス化、参照カウント、バージョン情報、フォールトトレランスなどの責任を担います。
アプリケーションとネットワークの透過性
COMオブジェクトは、プロセス内、プロセスの境界を越えて、またはDCOM経由でネットワークを超えてインスタンス化して参照できます。プロセスの外やリモートにあるオブジェクトは、マーシャリングを利用してメソッドコールや戻り値をやり取りできます。
COMのスレッド
COMは、アパートメントモデルという概念によってスレッドの問題を解決します。アパートメントは、単一のスレッドまたはスレッドのグループ内の実行コンテキストです。各COMオブジェクトは、1つのアパートメントに関連付けられます。
COMには、シングルスレッドアパートメント (STA)、マルチスレッドアパートメント (MTA)、中立アパートメント (NA) の3つのモデルがあります。STAでは、単一のスレッドがオブジェクトのメソッドを実行し、MTAでは、複数のスレッドがオブジェクトのメソッドを同時に実行します。NAは、メソッドがリエントラントである場合に利用され、STAとMTAの両方から直接呼び出し可能です。
脚注
参考文献
Dale Rogerson著、バウン グローバル株式会社訳『Inside COM』アスキー出版局、1997年。
ISBN 4-756-12176-4。
関連項目
Bonobo
外部リンク
COM (Component Object Model) - MSDN Library (英語)