COM、ActiveXコントロール、Microsoft Windows CE
Peggi Goodwin
Microsoft Corporation
1998年5月
概要
Microsoft(r) Windows(r)CEはコンパクトで反応が速く、堅牢なシステムになるようゼロから設計された新しいオペレーティング システムです。そのメモリ占有量の小ささと、応答速度の速さは、組み込みシステムだけでなく、各種の小型の消費者向け機器や、垂直市場向け機器にも理想的です。Windows CE上で稼動するよう設計されたアプリケーションもまた、応答性が高く、システム リソースを効率よく利用できなければなりません。
Microsoft ActiveX(r)コントロールは、小型で高速でパワフルな、自己登録型のCOMコンポーネントです。Component Object Model(COM)は、オブジェクト指向プログラミングの利点と、バイナリの再利用性、言語非依存性、バージョン管理能力、自己登録機能、ライセンス取得のしやすさを兼ね備えます。
本稿では、Component Object Modelを使用する利点、特にActiveXコントロールを使ったWindows CE向けソフトウェア開発と、以下について重点的に述べいます。
- COMとActiveXコントロールの起源についての説明。
- ActiveXコントロールとその前身であるOLEコントロールとの比較。
- COMとその利点の概要。
- IUnknownインターフェイスの説明。
- COMがポリモーフィズムとバージョン管理能力をサポートする方法。
- 継承を使わずにCOMがコードの再利用をサポートする方法。
- 事前バインディングと実行時バインディングの比較。
- GUIDとクラス ファクトリの説明。
- Windows CEオペレーティング システムの簡単な紹介。
- ActiveXコントロールの技術がいかにWindows CEと適しているか。
- COMおよびActiveX開発を容易にする、Windows CEツールキットに同梱のツールの紹介。
はじめに
Windows CEはコンパクトでありながら強力な新しいオペレーティング システムです。開発者は、標準Windows APIの知識さえあれば、多種多様な組み込みシステム、一般消費者向け機器、垂直市場向け機器を対象とするアプリケーションを、Windows CEを使って開発できます。ActiveXコントロールは、小型、高速、軽量で、リソースの使用効率がよいので、Windows CEベースのプラットホームにたいへんよくなじみます。
ActiveXコントロールや他のCOMコンポーネントを使用することで、Windows CEアプリケーションは、サイズや速度の面で妥協することなく現在使用可能な最先端のコンポーネント技術を活用することができます。再使用可能なコンポーネントを作成し、それをMicrosoft Visual Basic(r)やMicrosoft Visual C++(r)ベースのWindows CE用アプリケーションに埋め込むことができます。拡張性があり、バージョン管理が可能で、堅牢で、高度にモジュール化されたアプリケーションを作成し、Windows CE、Microsoft Windows NT(r)、インターネット上で実行できるようになります。
OLEという言葉は当初、Object Linking and Embedding(オブジェクトのリンクと埋め込み)の頭字語として使用されていました。その後Microsoftは、OLEという言葉をComponent Object Model(COM)に基づくあらゆる技術に対して使用しました。しかし現在は、OLEは再びObject Linking and Embeddingの頭文字として使われています。現在OLE技術として定義された技術のほとんどは、主にデスクトップ プラットホームに応用されています。
ActiveXコントロールはOLEに基づく技術で、元々は、インターネットとイントラネット プラットホームを主な対象としています。ActiveXコントロールの仕様は、OLEコントロールの仕様と比べ、はるかに融通性があり、OLEコントロールが実装しなければならないインターフェイスをすべて実装する必要はありません。ですから、ActiveXコントロールはOLEコントロールより小さく速く、効率的になれるのです。ActiveXの仕様は、サイズと速度を最適化することに特に力を入れて設計されたため、ActiveXコントロールはWindows CEの開発には理想的と言えます。その他の小さく効率的なインプロセスのCOMコンポーネントもまた、Windows CEに非常に適しています。
COMとActiveXの起源
ActiveXコントロールのルーツはObject Linking and Embedding(OLE)にあります。OLEの本来の目的は、複数のアプリケーションがドキュメント中心の方法で互いにやり取りできるようにすることでした。ドキュメント中心のコンピューティングの最終目的は、1つのドキュメント内で、異なるアプリケーションの機能をユーザーが利用でき、しかも複数のアプリケーションが実行されていることをユーザーに意識させないことでした。例えばMicrosoft Wordで文書を作成し、文書中にビットマップ画像を埋め込み、そのビットマップ画像を文書の一部として表示できます。このビットマップ画像を編集するには、画像の上をダブルクリックします。するとMicrosoft Paintが自動的に読み込まれ、Microsoft Paintのメニュー バーがWordのメニュー バーと組み合わされます。その後はWord文書を終了することなく、ビットマップ画像を編集できます。また、スプレッドシートと文書をリンクして、元のスプレッドシートを更新したときに、同時に文書中でも更新内容を自動的に反映させることができます。
OLE 1.0は1991年にリリースされました。この初期のバージョンは、Dynamic Data Exchange(DDE)に基づいていました。DDEは未熟な技術で、プログラムすることが難しく、あまり堅牢でもないという評価をすでに受けていました。残念ながら、この評価はOLEの最初のバージョンにも引き継がれてしまいました。
MicrosoftはDDEの制限をよく知っていました。そして、Component Object Model(COM)と呼ばれる、コンポーネントに基づく真新しい技術に取り組み始めていました。COMは、オブジェクト指向プログラミングの最も優れた面を採用し、これらに言語独立性、バージョン管理機能、分散処理機能の潜在能力を組み合わせるよう設計されました。
1992年に、MicrosoftはOLE 2.0を発表しました。OLE 2.0はCOMを基盤として使い、ゼロから再設計されていました。この新しいバージョンは、その前身と比べ堅牢であり、用途もはるかに拡大しました。COMの主な特徴は、新しい機能をコンポーネントに継ぎ目なく追加でき、そのコンポーネントのクライアントをまったく再コンパイルせずに新しいインターフェイスを追加できるという機能です。コンポーネントを新しいバージョンに置き換えるだけで、新しいクライアントは、直ちに新機能の利点を活用できるのです。一方、新しいインターフェイスに気付かないクライアントは、古いインターフェイスをそのまま使い続けることができます。COMには生来の拡張性があるので、バージョン番号は無意味となり、もはやOLEにも使用されなくなりました。
その間に、Microsoftは他の技術に取り組んでいました。この技術もまた、ActiveXコントロールの将来に影響を与える運命にありました。1991年、MicrosoftはBASIC言語に基づきVisual Basicと呼ばれるRapid Application Development(RAD:アプリケーション短期開発)ツールを発表しました。Microsoft Visual Basic(r) 2.0が1992年にリリースされたとき、これには新機能が含まれていました。この新機能が結果的に、Visual Basicを世界で最も普及したプログラミング言語の1つにしたのでした。この機能はVisual Basicコントロール、VBXとしても知られています。VBXは自己完結型のコード モジュールで、CまたはC++で書かれており、フォーム上にドラッグ アンド ドロップすることで、あらゆるVisual Basicベースのアプリケーションに埋め込めたのでした。
1993年、技術が32ビット プログラミング モデルへと移行するにつれて、Microsoftはジレンマに直面しました。VBXが16ビット アプリケーション用にしかコンパイルできなかったからです。Microsoftはプログラミング モデルを変更しなければなりませんでしたが、幸いにもこのときすでに、32ビット対応のCOMが開発されていたのです。おまけに、COMを使って開発されたコントロールは、CやC++だけでなくどの言語ででも記述でき、Visual Basicだけでなくどの言語で開発されたアプリケーション上でも動きました。これで、1993年にMicrosoftはOLEコントロール(OCX)を発表し、OCX技術がVBX技術に取って代わるだろうと予告したのです。当初は、開発者コミュニティの間に大きな抵抗がありました。VBXが浸透していて、すでに相当数が市場に出回っていたためです。しかし、OLEコントロールのきわめて大きなメリットに気付くにつれて、開発者たちは新しい技術を受け入れ始めました。
1995年、別のパラダイム シフトがコンピュータ業界で起こっていました。これが、前代未聞の人気を博したインターネットで、特にWorld Wide Webに人気がこれに拍車をかけました。常にデスクトップ コンピューティングに焦点を合わせていたMicrosoftは、新たな課題に直面しました。自社の既存技術をインターネット上での使用に合わせる方法を見い出すか、あるいはインターネット向けの完全に新しい技術を生み出さなければなりませんでした。インターネット コンピューティングに必要な条件は、デスクトップ コンピューティングの条件とかけ離れていました。デスクトップ コンピューティングについては、機能と使い易さを最大にすることがすべてでした。リソースは大きな問題ではありませんでした。というのも、RAMもハード ディスクも年々値下がりしていたからです。
しかし、インターネットに焦点を合わせたシフトで、すべてが変わりました。突如として、効率的なリソースの利用が最大の関心事となったのです。サイズの大きなコンポーネントを遅い電話線でダウンロードするのは、ただ能率が悪いだけでなく、ユーザーにとって受け入れがたいことでした。もしコンポーネントが、ダウンロードにあまりにも長い時間を必要としたら、ユーザーは苛立ってマウスをクリックし、よそのサイトへジャンプしてしまうでしょう。Microsoftは新しい、より柔軟性のある仕様を提供して、インターネットでの使用を目的に設計された、小く速い、軽量のコントロールを生産できるようにする必要があると気付いたのでした。
OLEコントロールとActiveXコントロールの違い
最初のOLEコントロールの仕様によると、どのコントロールも、自身のメソッドを公開するために実装しなければならないインターフェイスのほかに、少くとも9つの指定されたインターフェイス(合計60個のメソッドが含まれる)を実装しなければなりませんでした。その他に、コントロールにユーザー インターフェイスがあるかどうか、コントロールがイベント、プロパティ変更通知、アンビエント プロパティ、プロパティ セット、プロパティ ページ、外部接続をサポートするかどうかに応じて、7つのインターフェイスも必要でした。インターフェイスの標準化により、OLEコントロールはプログラムするのは容易でないにしても、使いやすくはなりました。コンテナ アプリケーションは、どのOLEコントロールからどのようなインターフェイスを期待できるかを正確に知ることができ、すべてのOLEコントロールを共通の方法で処理することができました。唯一の問題は、この機能をすべてサポートするためにOLEコントロールが大きくなりがちだったということで、その結果、インターネット上では実用的でなかったのです。
1996年、MicrosoftはActiveXコントロールの新しい仕様をリリースしました。この仕様で、ActiveXコントロールは、実質的にIUnknownという1つのインターフェイスと、DllRegisterServerとDllUnregisterServerという2つのAPI関数さえサポートしていればよくなりました。ActiveXコントロールは、OLEコントロールに必要なインターフェイスの標準セットをサポートする必要がないため、コンテナ側は、ActiveXについて、OLEコントロールを使用する場合よりもさらに詳しい知識が必要です。一方、ActiveXコントロールは、自身の処理を達成するために実際に必要なインターフェイスだけをサポートすればよいのです。その結果、ActiveXコントロールは小型で応答性を高いものになりました。
新機能
OLEコントロールとActiveXコントロールには、他にも違いがあります。重要な違いは、ActiveXコントロールはすべて自己登録型でなければならないことです。OLEコントロールや他のCOMコンポーネントの場合、これは必須ではありません。ActiveXの仕様では、表1にまとめた機能もサポートします。
表1:ActiveXの機能
ActiveXの新機能 | 説明 |
---|---|
ジャストインタイム アクティベーション | ActiveXコントロールは可視でありながら、アクティブでない状態のときがあります。ユーザーとの対話があるまでアクティベーションは延期されます。コントロールは、アクティブにされるまでは専用のウィンドウを作成しないため、コントロールがアクティブにされない場合は、時間とリソースが節約でき、Webページの読み込みも高速化できます。 |
非アクティブ状態でのマウス操作 | コントロールは、可視でアクティブにされていないときも、コンテナによって渡されたマウス メッセージを処理できます。コントロールがアクティブにされると、通常の方法でメッセージを処理します。 |
ちらつきのないアクティベーション | ActiveXコントロールが、アクティブのときとアクティブでないときのどちらの状態でも同じ方法で自身を描画する場合、このオプションは、アクティブでない状態からアクティブ状態に移行するときのコントロールの再描画を防止して、画面のちらつきを軽減します。 |
ウィンドウレス アクティベーション | ウィンドウレスActiveXコントロールには、専用のウィンドウがありません。コンテナは、ユーザーからの入力をコントロールに送る役割を担います。ウィンドウレス コントロールは読み込み速度が速く、矩形である必要がなく、背景を透明にすることもできます。 |
クリップされないデバイス コンテキスト | クライアント矩形領域の外側に描画しない場合、ActiveXコントロールは、このオプションを使用することで描画操作の速度を上げることができます。ウィンドウレス コントロールには効果ありません。 |
描画の最適化 | コンテナが複数のコントロールを1つのデバイス コンテキストへ描画する場合は、各コントロールが必要なGDIオブジェクトを選択します。各コントロールが、以前に選択されたオブジェクトを復元する必要がなければ、時間の節約になります。すべてのコントロールを描画した後、コンテナが元のオブジェクトを復元できます。 |
非同期プロパティ | Webページから高速でダウンロードするために、ActiveXコントロールはそのプロパティを非同期に読み込めます。この機能はWindows CEではサポートされません。 |
現在のCOMとActiveX
Component Object Model(COM)は、再利用可能、バージョン管理能力、言語非依存、マルチプラットフォーム対応バイナリ コンポーネントなどをサポートする目的で設計されています。COMオブジェクトは、色々な点で、オブジェクト指向プログラミングのパラダイムから馴染みの深い従来のオブジェクトに似ています。従来のオブジェクトのように、COMオブジェクトはカプセル化、抽象化、ポリモーフィズムを提供します。ですがCOMはバイナリ標準なので、COMオブジェクトは通常のオブジェクトにはない利点を提供します。
COMは再利用を、単にコード レベルではなく、バイナリ レベルでサポートします。COMコンポーネントはバイナリ オブジェクトなので、ユーザーはこれらを再コンパイルする必要なく再利用できます。その上、COM開発者はソース コードを配布する必要が決してありません。バイナリ コンポーネントの、その他の本質的な利点は、どんなクライアントでも言語(コンポーネントあるいはクライアントが実装された)に関係なく使用できると言うことです。
COMコンポーネントはバージョン管理もサポートします。これはつまり、コンポーネントの既存のクライアントに影響を与えることなく、COMコンポーネントに新機能を追加して新しいバージョンを配備できるということです。既存のクライアントは新しいコンポーネントを再コンパイルせずに、元々使用していたものと同様に使い続けることができます。新しいクライアントは、即座に新しい機能を利用できます。また、まだ新しいコンポーネントが配備されていない環境に新しいクライアントを配備した場合、新しいクライアントは従来のコンポーネントを使って機能します。単に新機能が使用できないだけです。
COMのもう1つの優れた機能は、ライセンス取得機能が組み込まれている点です。COMはランタイム専用のライセンス取得と、再配布用のライセンス取得の両方をサポートします。
ActiveXは、Microsoftが開発し、Open Groupが管理をしている公開標準規格です。ActiveXコントロールはすべてCOMコンポーネントです。しかし、ほかのCOMコンポーネントと違い、ActiveXコントロールは、DllRegisterServer関数とDllUnregisterServer関数を実装する必要があります。これにより、ActiveXコンポーネントは確実に自己登録型になります。
COMインターフェイスによるポリモーフィズムとバージョン管理機能のサポート
COMの最も面白い特徴の1つは、抽象化、ポリモーフィズム、バージョン管理をサポートするためにCOM自身がインターフェイスを使用する方法です。COMコンポーネントは複数のインタフェースを実装できます。各インターフェイスは、クライアントに対して、コンポーネントの機能を抽象化したものを提示します。
インターフェイスはC++の抽象クラスに似ていて、メソッドはすべて純粋な仮想関数です。インターフェイスは不変です。インターフェイスを一度公開した後は、メソッドの追加や削除はできません。これは、インターフェイスが本質的にCOMコンポーネントとそのクライアントの間の契約だからです。契約は、コンポーネントがインターフェイスによって公開されたすべてのメソッドを実装し、各メソッドを、コンポーネントのタイプにふさわしい方法で実装することを保証します。公開さていているインターフェイスに規定されている通りにメソッドが動作する限り、2つの異なるコンポーネントが異なる方法で、同じメソッドを実装できます。これが、COMがポリモーフィズムをサポートする方法です。
COMは、バージョン管理をサポートするためにもインターフェイスを使用します。COMコンポーネントの新しいバージョンを作成する場合は、新しい機能を公開する新しいインターフェイスを加えます。しかし、新しいメソッドを既存のインターフェイスに加えることができません。新しいメソッドを追加すると、不変の原則を破ることになるからです。
IUnknownインターフェイス
IUnknownと呼ばれる、すべてのCOMコンポーネントに共通のインターフェイスがあります。すべてのCOMインターフェイスはIUnknownから継承します。IUnknownインターフェイスは、QueryInterface、AddRef、Releaseという3つのメソッドを公開します。どのインターフェイスもIUnknownから継承をしているので、クライアントは、それが保持しているポインタが指す任意のインターフェイスのメソッドを実行できます。すべてのCOMインターフェイス メソッドの中で、おそらくQueryInterfaceが一番重要です。クライアントはQueryInterfaceを呼び出し、オブジェクトが特定のインターフェイスをサポートしているかどうかを調べ、インターフェイスに対する参照を取得します。AddRefとReleaseはメモリ管理に使用されます。COMコンポーネントの各インスタンスには参照カウントがあります。QueryInterfaceなどのメソッドがインターフェイス ポインタをクライアントに返すとき、メソッドは、必ず当該インターフェイスのAddRefを呼び出さなければなりません。この呼び出しにより、インスタンスの参照カウントがインクリメントされます。クライアントは、インターフェイスを使い終わったら、必ずインターフェイスのReleaseを呼び出して、参照カウントをデクリメントしなければなりません。参照カウントがゼロになるとインスタンスは削除され、占有していたメモリ領域が解放されます。
包含と集成を介したコードの再利用
COMは複数のインタフェース継承をサポートします。しかし実装の継承はサポートしません。COMは実装の継承をサポートしないので、真のオブジェクト指向でないと主張する人もいます。しかし、実装継承の目的がポリモーフィズムとコードの再利用をサポートすることで、COMはそれらを両方ともサポートしているため、実装継承の欠如は、制限というよりは手法の違いといえます。先に説明したように、COMはインターフェイスを介してポリモーフィズムをサポートし、包含と集成を介してコードの再利用をサポートしています。
あるクラスから別のクラスを派生させるのではなく、包含を介してコードを再利用するには、単に再利用したいコンポーネントを、新しいコンポーネントのプロパティとして含めるだけです。新しいコンポーネントは、必要なときはいつでも、本来のコンポーネントのメソッドに権限を委譲できます。
集成を使用するためには、集成しているコンポーネントによって実装されたインターフェイスとともに、本来のコンポーネントのインターフェイスを直接公開します。クライアントから見れば、両方のインターフェイス セットが同じコンポーネントに属しているように見えます。ただし、IUnknownメソッドは、必ず集成しているコンポーネント(クライアントに見えているほう)上で実行されるような方法で実装しなければなりません。これには理由が2つあります。1つは、COMでは、クライアントが特定のオブジェクトのIUnknownインターフェイスへのポインタを要求するときは必ず、戻されるポインタが常に同じアドレスを参照しなければならないことです。これにより、クライアントは、2つのポインタが同じオブジェクトを参照しているかどうか比較できるようになっています。
もう1つの理由は、少し複雑です。クライアントが内側のコンポーネント(集成されているコンポーネント)に属すインターフェイスを要求しているとします。外側のコンポーネント(集成しているコンポーネント)は、要求されたインターフェイスを戻します。クライアントは、内側のコンポーネントに属すインターフェイスに対してQueryInterfaceを呼び出し、外側のコンポーネントによってサポートされているインターフェイスを要求すると考えてください。内側のコンポーネントは、要求された特定のインターフェイスをサポートせず、そのインターフェイスが外側のコンポーネントによってサポートされているかどうかを知る方法もありません。内側のコンポーネントを開発した段階では、開発者は、どの種類のコンポーネントがそれを集成するか知ることができません。内側のコンポーネントは、HRESULT値として、インターフェイスが実装されていないことを示すE_NOTIMPLを戻すはずです。外側のコンポーネントを単独のオブジェクトとして見るクライアントには、内側のコンポーネントと対話をしていることを知る方法がありません。内側のコンポーネントが存在することすら知らないのです。
解決策は1つあります。コンポーネントが他のコンポーネントを集成する場合は、それをインスタンス化するときに、そのIUnknownポインタを内側のコンポーネントに渡すようにします。インスタンス化されたコンポーネントが集成をサポートない場合は、HRESULT値としてCLASS_E_NOAGGREGATIONを戻し、集成できないことを示します。コンポーネントが集成をサポートする場合、コンポーネントは外側のコンポーネントのIUnknownポインタをキャッシュし(制御用Unknownといいます)、すべてのIUnknown呼び出しを制御用Unknownへ委譲します。実装継承の代わりに包含または集成を使うと、クラス階層を横断する負荷を回避できるため、オブジェクトの応答速度が全般的に速くなります。
実行時バインディングと事前バインディング
IUnknownは、すべてのCOMコンポーネントがサポートする必要のある唯一のインターフェイスですが、大部分のActiveXコントロールは、IDispatchインターフェイスもサポートしています。IDispatchをサポートするCOMコンポーネントは、オートメーション サーバーと呼ばれます。IDispatchインターフェイスが公開するメソッドは、ダイナミック バインディング(実行時バインディングとしても知られています)をサポートしています。実行時バインディングは、クライアントが実行時に動的にコントロールのメソッドを実行できるようにするテクニックで、コンパイル時に、コントロールがどんなメソッドを提供するのか、どのパラメータをメソッドが受け取るのかを知っている必要はありません。実行時バインディングを使うと、ポインタをサポートしない言語で書かれたクライアントも、ActiveXコントロールを使用できます。
インターフェイスはCOMによって、仮想関数テーブル(vtable)として内部的に実装されます。仮想関数テーブルは仮想関数へのポインタからなるテーブルです。vtableバインディングは事前バインディングとしても知られています。CあるいはC++に書かれたクライアントは、仮想関数テーブル バインディングを使って、ActiveXコントロールのメソッドを直接呼び出すことができます。事前バインディングは、バインディングを実行時ではなくコンパイル時に行うため、ダイナミック バインディングよりも高速です。ただし、Visual Basic、Java、Webページでよく使われる一般的なスクリプティング言語はポインタをサポートしていないため、このような言語を使う場合は仮想関数テーブル バインディングを使用できません。これらの言語で書かれたクライアントは、ダイナミック バインディングを使用しなければなりません。デュアル インターフェイスを持つコントロールは、事前(仮想関数テーブル)バインディングと実行時(ダイナミック)バインディングの両方をサポートします。
COMオブジェクトはどこから来るのでしょう?
すべてのCOMコンポーネントには一意のクラス識別子(CLSID)があり、すべてのインターフェイスには一意のインターフェイス識別子(IID)があります。CLSIDとIIDは、すべてのコンポーネントに渡り一意の識別子(GUID)です。GUIDは特殊なアルゴリズムで生成される128ビットの数値です。このアルゴリズムは、それが動作しているマシンのEthernetカード番号と、GUIDを作成したときの正確な時刻を使って、すべてのGUIDの一意性を保証します。CLSIDとIIDは、すべてのCOMコンポーネントとインターフェイスに、開発時に割り当てられます。クラスとインターフェイスは、内部ではGUIDによって識別されるので、名前の衝突にまつわる心配はありません。GUIDが憶えがたいことは周知の事実なので、コンポーネントには、憶えやすい名前もあり、それがレジストリの中でGUIDにマップされています。
どのCOMコンポーネントにもクラス ファクトリがあります。クラス ファクトリは、IClassFactoryインターフェイスを実装する特殊なオブジェクトです。クライアントは、COMコンポーネントのインスタンスを生成する必要が生じると、COMの実行時環境からコンポーネントのクラス ファクトリへのポインタを要求します。COMは、クライアントによってそれに渡されたCLSIDを使ってレジストリを検索し、コンポーネントとそのクラス ファクトリが格納されているダイナミック リンク ライブラリ(DLL)または実行可能プログラムの場所を突き止めます。クライアントはその後、IClassFactoryを使って、クライアントに必要なだけコンポーネントのインスタンスを生成できます。クライアントは、オブジェクト上のどのインターフェイスをクライアントが必要とするかをインターフェイスのIIDを渡すことによって、クラス ファクトリに教えます。クラス ファクトリは、オブジェクトのインスタンスを生成し、その上にAddRefを呼び出した後に、要求されたインターフェイスへのポインタをクライアントへ戻します。クライアントは、その後QueryInterfaceを呼び出して、同じオブジェクト上でアクセスする可能性のあるすべてのインターフェイスへのポインタ取得します。クライアントはクラス ファクトリを使い終わったら、クラス ファクトリに対してReleaseを呼び出さなければなりません。クライアントが特定のオブジェクトのインスタンスを1つだけ必要とする場合はCoCreateInstance関数を呼び出すことができます。COMはクラス ファクトリをインスタンス化し、要求されたインターフェイスへのポインタを取得し、それをクライアントへ戻し、クラス ファクトリを解放します。このようにするとクライアントは、クラス ファクトリを直接扱う必要がなくなります。
Windows CE
Windows CEは、コンパクトで反応が速く、堅牢なシステムになるようゼロから設計された新しいオペレーティング システムです。そのメモリ占有量の小ささと、応答速度の速さは、組み込みシステムだけでなく、各種の小型の消費者向け機器や、垂直市場向け機器にも理想的です。Windows CEオペレーティング システムと、ほかの組み込みオペレーティング システムや一般消費者向け電子機器との差は、それが急速に業界標準になりつつあるという事実です。従来、組み込みオペレーティング システムは、比較的少数の開発者だけに知られていたメーカー独自のシステムで、根本的に特定のプラットフォームに縛られていました。開発者は、自ら選んで、あるいは必要に迫られて、あるプラットフォームから別のプラットフォームに移行するときに、苦労して身につけた技術を活かすことができませんでした。Windows CEでは、一般消費者向け電子機器や組み込みシステムの開発者は、一度だけ学習すれば、その後はどこでもプログラミングができます。デスクトップ プラットフォームで使われているWindowsのアプリケーション プログラミング インターフェイス(API)に精通しているプログラマは、世界中には何百万といます。今、組み込みシステムの開発者は、これと同じ多くのAPIと、Windows CE用に特別に作成された少数の新しいAPIを使用することができるのです。
Windows CEとActiveXの結合
Windows CEはメモリ占有量の小さなオペレーティング システムであり、多くのWindows CEベース プラットフォームは、リソースに大きな制約があります。その結果、Windows CE上で実行することを目的として設計するアプリケーションとコンポーネントは、小型でシステム リソースを有効に利用できるものでなければなりません。Windows CEはリアルタイム オペレーティング システムなので、この上で実行するように設計されたコンポーネントは、応答性に優れ、堅牢でなければなりません。
サイズ、速度、信頼性は、インターネット用のコントロールを設計するときにも際重要課題です。インターネットには、小さく速く効率的で、堅牢なコントロールが必要なのです。コントロールが大きすぎてダウンロードに長い時間がかかったら、ユーザーは待ってくれません。反応が速くなかったら、ユーザーは何か別のものをクリックしに行くでしょう。コントロールが初回に動かなければ、ユーザーは次のチャンスを与えるために戻って来てくれたりはしません。
ActiveXの仕様は、当初インターネット コントロールを作成するための仕様として計画されたため、同じ要素がインターネットとリアルタイム アプリケーション両者の有効性にとってきわめて重要なため、ActiveXコントロールの技術は、あらゆるWindows CEプラットフォームの必要条件を理想的に満たすことになります。自己登録機能はWindows CEの必要条件ではないので、ほかのCOMコンポーネントもまた同様に、Windows CEベースの開発の必要条件を満たすでしょう。
Windows CEでのCOMとActiveXのサポート
Windows CEは、デスクトップ型Windowsプラットフォームでサポートされている標準のCOM機能をほとんどサポートします。最も大きな違いの1つは、Windows CEがフリー スレッド コンポーネントのみをサポートすることです。Windows CEでは、アパートメント スレッドやシングル スレッド モデルはサポートされません。このために、Windows CE用に設計されたすべてのCOMコンポーネントとActiveXコントロールは、リエントラントであることが必要です。
もう1つの違いは、デスクトップ プラットフォーム上のCOMコンポーネントがインプロセス サーバーやプロセス外サーバー、またWindowsサービスになる可能性があることです。Windows CEは、インプロセスCOMサーバーだけをサポートします。
COMサーバーは、1つ以上のCOMコンポーネントのほかに、クラス ファクトリと自己登録関数が含まれているモジュールです。さらに、サーバーをメモリから安全にアンロードできるタイミングを判断するために、実行時の環境でCOMによって呼び出される関数も含まれています。インプロセス サーバーは、呼び出し元プロセスのアドレス空間に直接読み込まれる、ダイナミック リンク ライブラリ(DLL)です。プロセス外サーバーとWindowsサービスは、それ自体のアドレス空間の中で実行される、スタンドアローンの実行プログラムです。インプロセス サーバーはホストと同じアドレス空間で実行されるので、呼び出しごとにプロセス間でのマーシャリングに伴うオーバーヘッドが生じません。インプロセスで実行されているオブジェクトのメソッドに対する呼び出しは、ホスト プロセスで定義されているオブジェクトに対する呼び出しと同じ速度で呼び出せます。
現在Windows CEは、非同期のモニカや非同期のストレージをサポートしていません。Windows CEでは、アプリケーションがVARIANTを渡すことはできませんが、VARIANT*を渡すことはできます。Microsoft Pocket Internet Explorerは、ActiveXコントロールを現在サポートしていません。
Microsoft Windows CE Toolkit for Visual Basic 5.0と、Microsoft Windows CE Toolkit for Visual C++ 5.0の両方が、ActiveXコントロールの使用をサポートし、ActiveXコンテナ作成用の優れたツールを提供しています。Windows CE Toolkit for Visual C++ 5.0は、さらに、ActiveXコンポーネントの作成を支援するための2つの強力なライブラリも提供します。
Windows CE Toolkit for Visual C++ 5.0
Windows CE Toolkit for Visual C++ 5.0は、ActiveXコンポーネントの作成用に3つのオプションを提供します。ユーザーは標準のWindows CE SDK OLE API、Microsoft Foundation Class Library for Windows CE、またはActive Template Library for Windows CEを利用することができます。Microsoft Foundation Class Library(MFC)for Windows CEは強力なクラス ライブラリであり、C++でWindows CEのプログラムを作成するための完全なオブジェクト指向アプリケーション フレームワークでもあります。MFC for Windows CEは、ActiveXコンテナ作成用の優れたツールです。ActiveXコントロールをサポートするコンテナをMFCプロジェクトに加えるために、MFC for Windows CEのAppWizard(exe)のステップ2でActiveXのサポートを選択してください。また、MFC for Windows CE ActiveX ControlWizerdを使用すれば、MFC for Windows CEを使用するActiveXコントロールも作成できます。
Active Template Library(ATL) for Windows CEは、可能な限り小さく高速なActiveXコンポーネントの作成を支援するために設計され、最適化されたC++のテンプレート ライブラリです。ATL for Windows CEを使用するActiveXコンポーネントを作成するには、ATL for Windows CE COM AppWizardを使用します。
ATLを使用すれば、MFCを使用するよりも小型、高速、高効率のコンポーネントとコントロールを作成できます。しかし、ActiveXコントロールを作成するために、MFC for Windows CEの使用を優先させることがあるかもしれません。MFCは、特にユーザー インターフェイスを持つコントロールを作成する場合は、よい選択となります。MFCはATLよりさらに成熟したライブラリなので、ATLにはない、完全なコントロール用の特定機能をサポートしています。
まとめ
本稿では、COMとActiveXコントロールの持つ多くの機能と利点を説明し、それらをWindows CEベースの開発に取り入れる方法を説明しました。
Component Object Modelが継承の実装なしにポリモーフィズムをサポートする方法や、クライアントを再コンパイルせずにコンポーネントのアップグレードを可能にする方法を説明し、包含と集成を使用する方法も解説しました。本稿ではさらに、スクリプティング言語など、異なるプログラミング言語で書かれたクライアントでCOMコンポーネントを使用する方法も示しました。また、事前(仮想関数テーブル)バインディングと実行時(ダイナミック)バインディングの利点と不利な点を挙げ、どのようにすれば同じCOMコンポーネントでその両方をサポートできるかを示しました。すべてのコンポーネントとインターフェイスが一意のIDを持つ方法を説明し、これによりCOMはたとえ同じ名前が付いていても、コンポーネントを他のものと間違えたりしないことも説明しました。クライアントがコンポーネントをインスタンス化する方法と、それらの様々なインターフェイスへのアクセス方法を示し、さらに、ActiveXコントロールが本質的には自己登録型のCOMコンポーネントであることも説明しました。
最後に、本稿では、Windows CEオペレーティング システムを簡単に紹介し、Windows CEがサポートするComponent Object Modelの範囲について検討しました。そして、なぜActiveXがWindows CEの開発に適しているかを述べ、Windows CE向けのアプリケーション用にCOMコンポーネント、ActiveXコントロール、コンテナを作成するときに利用できるツールの概要をもって結びとしました。
詳細情報
Peggi Goodwin著、「Windows CE対応Microsoft Foundation ClassライブラリとActive Template Library」