COM以前
Windows3.1により、ワープロ内に表計算ソフトで作成したグラフなどを「カット&ペースト」、つまりデータの切り貼りを簡単に行うことが可能になった。
その次にデータの関係を構築しておくと、データが修正されたら自動的に反映される、いわゆるDDEというメカニズムがとりこまれた。DDEはデータのやり取りだけができる、クライアントとサーバーの関係をもっていたが、DDEはデータの大きさなどに制限があった。
次にでてきたものがOLE (Object Link and
Embedding)である。これは、Wordを使用している中に、Excelワークシートを添付しクリックすると、Excelが別に起動するのではな
く、Word自身のメニューがExcelのそれと入れ替わってしまうように、複数のアプリケーションによりひとつのドキュメントを作成できる機能のことで
ある。(もっとも現在、こういう文書をOLEドキュメントと呼ぶ)当初のOLEは混乱が激しかったようで、有名なテクニカルライター全員が泣いていた。
複数のアプリで構成されるドキュメントへの解決策は、一般的なプログラム開発にも必要な技術であった。複数アプリケーションにより、あらたなひとつのアプ
リケーションを作っていくという考え方(コンポーネントアーキテクチャという)をインプリメントしたものが、COMである。
COMはインターフェースの定義の仕方
COMの基本はインターフェースの定義だけである。具体的には、あらゆるプログラミングインターフェースはIUnkownというインタフェースを継承しな
くてはならない。これにより、COMにのっとって開発されたプログラムを利用するならば、IUnknownに問いあわせればどういうインターフェースを
もっているかわかることになる。
インターフェースは複数もつことは可能である。もちろん各インターフェースもIunknownをもたねばならない。また、Iunknownにセットする最
初のいくつかのインターフェースポインタは決まった使い方をしなくてはならない。後述するAddreff,Relaseなどの機能を実装する。
WindowsがC++で開発されていることから、当初はインターフェースのリスト(Vtableと呼ばれる)は、ポインタだけであった。しかし
Visual Basicのようなポインタをサポートしていない言語では極めて使いにくい。そこで、COMとしては必須ではないが、Idispatchと
いうインターフェースが出てきた。最近のCOMではこちらを用意するのが普通である。Idispatchはインターフェースを名称で呼び出すことができ
る。Idispatch::Invokeにより具体的なメソッドを呼ぶことができるようになっている。このように、IunknownとIdispatch
の両方をもつことをデュアルインターフェースという。
長々と書いたCOMインターフェースはプログラムそのものとは別にIDL(Interface Definition Language)で定義し、コン
パイルし、タイプライブラリとしてモジュール内に保管される。Delphiではこの作業が色濃く残っており、タイプライブラリーの編集はプログラムの作成
と別作業になっている。プログラマが具体的に「あー、COMを作っているんだな。」と感じる作業である。
モジュールのみをダウンロードして実行した場合、IDLの内容はレジストリに書かれる。このことを「自己登録機能」という。明確に登録だけさせたい場合はプログラムの後ろに/REGSERVERとつけて実行する。
以上よりCOMが最低限もたねばならないとされている機能は、説明したIunknownインターフェースをそなえることと、レジストリ自己登録機能である。ところがこれだけの知識でCOMを作成できないから苦労する。
その他にCOMで決められていること
先に説明をおいておいた、Iunknownインターフェースに必ずセットされるメソッドについて述べよう。COMは誰かが使用中か誰も使用していないかを
管理している。もし、誰も使用していないのであればメモリー内に存在する意味はない。逆に、誰かが使用しているのに勝手に終了してはならない。そのため、
AddrefとReleaseというインターフェースを必ず装備せねばならない。
ユーザーは使用するたびに、Addrefを呼び出し使用することを宣言し(内部では参照カウントを+1)、使用が終了するとReleaseを呼び出す(内部では参照カウントを-1)。誰も使用していなければ(参照カウントが0)終了する。
また、COMの名称はクラスIDと呼ばれこの世で唯一無二でなければならない。クラスID(GUID)は、128ビットのユニークな名称が自動的に付加さ
れる。COM_Serverなどという名称は、世界で誰かがたまたま同じものを作るかも知れない。そこで、時間とLANカードのIDなどにより、必ずユ
ニークな名称がつけられる。これが真の名前となる。DCOMなどの場合、このGUIDで呼び出さねばならないことがある。
COMのプログラムとしての振る舞いの規定
ところでCOMはインターフェースの定義であるといっても、オブジェクトの起動、停止をもアーキテクチャに含む。これらをコントロールするために、システムに存在するものがCOMライブラリーであり、COで始まるインターフェースをもつ。
あるCOMが最初に呼び出された場合、ClassFactoryと呼ばれるCOMサービスにより起動(CoCreateInstance)され、インターフェースへのポインターは作成される。ユーザーが誰もいなくなったとき、COMは破棄される。
オブジェクトのクラス名をクライアントが要求すると、そのクラスをサポートするサーバーを起動する。サーバーは、
- クライアントと同じプロセス内
- クライアントと同じマシン上、ただし、別プロセス
- ネットワークを利用した別のマシン上
に存在しうる。最後のような別マシン上のサーバーと通信できる機能を特に、DCOMという。別マシンとの通信にはRPC(Remote Procedure Call)が使用される。
DCOMでは異機種間でも問題なく動くように、データの形式が異なっていると修正する機能「マーシャリング」がなされるようになっている。例えば、ダブル
ワードのワード長をもっているプラットフォームと、ワード長のプラットフォームでは形式が違う。この差異を吸収するのが「マーシャリング」である。
DCOMでは本来、このマーシャリング機能をプロキシー(送り側)とスタブ(受け取り側)といわれるモジュールにインプリメントしなくてはならない。忘れ
てほしくないのだが、このようにすることでCOM自身がデータ変換を考慮しなくてよくなる。
しかも、実際のマイクロソフトの製品ではOLEVariantにしうる値(WideString,Integerなど)ならばデフォルトのマーシャリング機能がサポートする。
アパートメントモデル
最後にスレッドとCOMについて記述する。
スレッドはOSがCPU資源を与える管理単位である。つまりひとつのプロセス内部に複数のスレッドはありうる。例えば、MS Wordの画面をコントロールするスレッドとプリント結果をキューするスレッドは別である。
これらのスレッドが共存するためには、相互関係を意識したコードが必要となる。しかし、ほとんどのプログラム(例えばVBでなにげなく書いたプログラム)
がスレッドについて意識していることは期待できない。COMでは「アパートメントモデル」という考え方でスレッドに対応、対応していないプログラム共に管
理する。
まず複数スレッドなど気にしないプログラムはシングルスレッドアパートメント(STA)として管理する。これはひとつのスレッドにひとつのCOMオブジェ
クトが存在し、そのスレッド内のクライアントのみがオブジェクトのメソッドを呼べる。もし、要求が複数きた場合、要求はキューにいれられ、順々に処理され
る。
WindowNT4.0ではフリースレッドもしくはマルチスレッドアパートメントと呼ばれるひとつのCOMオブジェクトを複数のスレッドで同時にクライア
ントが使用できるようになった。ただし、プログラマーは複数のスレッドが同時に動くことを考慮(スレッドセーフ)であることを考慮せねばならない。
なお、ひとつのプロセス内にはMTAを使う場合は、ひとつのアパートメントだけで十分であるとする。なぜならばMTAは複
数のスレッドをサポートするからである。逆にSTAを複数動かすことができるところが、COMの素晴らしさであろう。このため何も考えないVBプログラム
が複数スレッドで動くことができるのである。
|