(57)【特許請求の範囲】
【請求項１】
ＣＰＵ及びメモリを有し、前記ＣＰＵが前記メモリ内のサーバ・コンポーネントに接続された前記メモリ内の複数のクライアント・コンポーネントに通知するためのコンピュータ・システムにおける方法であって、前記各クライアント・コンポーネントは関数メンバを持つクライアント・コンポーネント・インタフェースを有し、前記サーバ・コンポーネントは前記クライアント・コンポーネントを前記サーバ・コンポーネントへ接続させるためのコンポーネント・マネージャと、更にユーザ・コンポーネントとを有し、前記コンポーネント・マネージャは各接続されたクライアント・コンポーネントの前記クライアント・コンポーネント・インタフェースへのリファレンス情報を有し、
（１）前記クライアント・コンポーネント・インタフェースが、入力手段を介して指定されたサービス要求を受信するステップと、
（２）前記ＣＰＵの指令を受けたコンポーネント・マネージャが、前記メモリ又は記憶手段内に記憶されたプログラミング情報を読み出し、当該プログラミング情報に基づき前記受信されたサービス要求に対応する前記クライアント・コンポーネント・インタフェースの関数メンバの実現を有するマルチキャステイング・オブジェクトを生成して前記メモリ内に記憶するステップと、
（３）前記ＣＰＵの指令を受けたユーザ・コンポーネントが、前記生成されたマルチキャステイング・オブジェクトに関する前記クライアント・コンポーネント・インタフェースの前記関数メンバを呼出すステップと、そして、
（４）前記マルチキャステイング・オブジェクトに関するクライアント・コンポーネント・インタフェースの前記呼出された関数メンバの制御下で、
前記ＣＰＵが、前記クライアント・コンポーネントの各々について、
(i)前記クライアント・コンポーネント・インタフェースへの前記リファレンス情報を検索するステップと、
(ii)前記クライアント・コンポーネントへ通知するために前記検索されたリファレンス情報により参照される前記クライアント・コンポーネント・インタフェースの前記関数メンバを呼出すステップと、を含む方法。
【請求項２】
コンポーネント間でインタフェースを共有するコンピュータシステムであって、
ＣＰＵ及びメモリを有するとともに、サーバ・コンポーネント部とクライアント・コンポーネント部を含み、
前記各クライアント・コンポーネント部は関数メンバを持つクライアント・コンポーネント・インタフェース部を有し、前記サーバ・コンポーネント部は前記クライアント・コンポーネント部を前記サーバ・コンポーネント部へ接続させるためのコンポーネント・マネージャと、更にユーザ・コンポーネント部とを有し、前記コンポーネント・マネージャは各接続されたクライアント・コンポーネント部の前記クライアント・コンポーネント・インタフェースへのリファレンス情報を有し、
（１）前記クライアント・コンポーネント・インタフェース部において、入力手段を介して指定されたサービス要求を受信する手段と、
（２）前記コンポーネント・マネージャ部の指令に基づき、前記メモリ又は記憶手段内に記憶されたプログラミング情報を読み出し、当該プログラミング情報に基づき前記受信されたサービス要求に対応する前記クライアント・コンポーネント・インタフェース部の関数メンバの実現を有するマルチキャステイング・オブジェクトを生成して前記メモリ内に記憶する手段と、
（３）前記ユーザ・コンポーネント部の指令に基づき、前記生成されたマルチキャステイング・オブジェクトに関する前記クライアント・コンポーネント・インタフェース部の前記関数メンバを呼出す手段と、
（４）前記マルチキャステイング・オブジェクトに関するクライアント・コンポーネント・インタフェース部の前記呼出された関数メンバの制御下で、
前記クライアント・コンポーネント部の各々について、
(i)前記クライアント・コンポーネント・インタフェース部への前記リファレンス情報を検索する手段と、
(ii)前記検索されたリファレンス情報により参照される前記クライアント・コンポーネント・インタフェース部の前記関数メンバを呼出す手段とを備え、前記サーバ・コンポーネント部に接続された複数のクライアント・コンポーネント部に通知がされることを特徴とするコンピュータシステム。
【請求項３】
ＣＰＵ及びメモリを有し、前記メモリ内のサーバ・コンポーネントに接続された前記メモリ内の複数のクライアント・コンポーネントへメッセージを送信するためのコンピュータ・システムにおける方法であって、前記サーバ・コンポーネントはコンポーネント・マネージャ及びユーザ・コンポーネントを含み、前記複数のクライアント・コンポーネントのそれぞれは関数メンバを有するクライアント・コンポーネント・インタフェースを提供し、前記サーバ・コンポーネントは各クライアント・コンポーネントの前記クライアント・コンポーネント・インタフェースへのリファレンス情報を有し、
（１）前記クライアント・コンポーネント・インタフェースが、入力手段を介して指定されたサービス要求を受信するステップと、
（２）前記サーバ・コンポーネントのユーザ・コンポーネントの制御下で、前記サーバ・コンポーネントのコンポーネント・マネージャのプログラミング命令を実行する前記ＣＰＵが、前記受信されたサービス要求に対応する前記クライアント・コンポーネント・インタフェースの関数メンバの実現を有するマルチキャステイング・オブジェクトを生成して前記メモリ内に記憶するステップと、
（３）前記ＣＰＵが、前記マルチキャステイング・オブジェクトのクライアント・コンポーネント・インタフェースの関数メンバを呼出すステップと、
（４）前記マルチキャステイング・オブジェクトに関するクライアント・コンポーネント・インタフェースの前記呼出された関数メンバの制御下で、
前記ＣＰＵが、クライアント・コンポーネントの各々に対して、
(i)前記クライアント・コンポーネントの前記クライアント・コンポーネント・インタフェースへの前記リファレンス情報を検索するステップと、
(ii)検索されたリファレンス情報により参照される前記クライアント・コンポーネント・インタフェースの前記関数メンバを呼出すステップと、を含む方法。
【発明の詳細な説明】
【０００１】
【技術分野】
この発明は、コンポーネントの接続（コネクト：connect ）管理を行うためのコンピュータの方法およびシステムに関する。
【０００２】
【従来の技術】
コンピュータ・システムでは、オブジェクト指向型の手法がよく用いられる。オブジェクトは、インスタンス・データ（データ・メンバ）、およびオブジェクトの振る舞いを規定するメンバ関数（メソッド）から構成される。図１は、オブジェクトの表現に使用する典型的なデータ構造を示すブロック図である。オブジェクトの表現に使用するデータ構造は、インスタンス・データ構造体1A01、仮想関数テーブル1A02、および関数メンバ1A03、1A04、1A05から構成されている。インスタンス・データ構造体1A01は、仮想関数テーブル1A02へのポインタおよびデータ・メンバを有する。仮想関数テーブル1A02は、そのオブジェクト用に定義された各仮想関数メンバのエントリ（項目）を有する。各エントリは、対応する関数メンバを実行するコードへのリファレンス（参照）を含んでいる。このオブジェクトのサンプルのレイアウトは、1991年４月９日に出願された米国特許出願第07/682,537号の「オブジェクト指向型プログラミング言語のコンパイラにおける仮想ファンクションと仮想ベースを実行する方法」（“METHOD FOR IMPLEMENTING VIRTUAL FUNCTIONS AND VIRTUAL BASES IN A COMPILER FOR AN OBJECT ORIENTED PROGRAMMING LANGUAGE ”）に示されたモデルと同じである。以下に、オブジェクトは、プログラミング言語Ｃ++によって定義されるクラスのインスタンスとして示される（もちろん、他のプログラミング言語を用いてオブジェクトを定義できることはいうまでもない）。
【０００３】
プログラミング言語Ｃ++においては、オブジェクト指向型の手法が、クラスの使用によりサポートされる。クラスは、ユーザが定義する型（タイプ）である。クラスの宣言では、そのクラスのデータ・メンバおよび関数メンバが記述される。例えば、次の宣言は、CIRCLEという名前のクラスのデータ・メンバおよび関数メンバを定義している。
【０００４】
0004027679.tif 000002
【０００５】
変数ｘとｙは円の中心の位置を示すもので、変数radiusは円の半径を示すものである。これらの変数は、クラスCIRCLEのデータ・メンバと呼ばれる。関数drawは、指定された位置に指定された半径の円を描く、ユーザが定義した関数である。関数drawは、クラスCIRCLEの関数メンバと呼ばれる。クラスのデータ・メンバおよび関数メンバは、その関数がそのクラスのインスタンスに操作を施すという点において、ともに結合されている。クラスのインスタンスは、そのクラスのオブジェクトとも呼ばれる。
【０００６】
Ｃ++の構文において、次の文（ステートメント）は、クラスCIRCLE型のオブジェクトａおよびｂを宣言するものである。
【０００７】
CIRCLE  ａ，ｂ；
【０００８】
この宣言により、オブジェクトａおよびｂのメモリが割り当てられる。次の文は、オブジェクトａおよびｂのデータ・メンバにデータを割り当てるものである。
【０００９】
a.x   = 2;
a.y   = 2;
a.radius = 1;
b.x   = 4;
b.y   = 5;
b.radius = 2;
【００１０】
次の文は、オブジェクトａおよびｂによって定められる円を描くために使用される。
【００１１】
a.draw();
b.draw();
【００１２】
派生クラス（derived class ）は、その基底クラス（base class）の特徴（データ・メンバおよび関数メンバ）を継承するクラスである。例えば、次の派生クラスCIRCLE-FILL は、基底クラスCIRCLEの特徴を継承する。
【００１３】
0004027679.tif 000003
【００１４】
この宣言は、クラスCIRCLE-FILL が、その宣言に導入されたデータ・メンバおよび関数メンバ（すなわち、データ・メンバpattern および関数メンバfill）に加えて、クラスCIRCLEの全てのデータ・メンバおよび関数メンバを含むことを示している。この例では、クラスCIRCLE-FILL は、データ・メンバｘ、ｙ、radiusおよびpattern 、ならびに関数メンバdrawおよびfillを有する。クラスCIRCLE-FILL は、クラスCIRCLEの特徴を「継承する」（インヘリット：inherit ）と呼ばれる。他のクラスの特徴を継承するクラスが、派生クラス（例えば、CIRCLE-FILL ）である。他のクラスの特徴を継承しないクラスが、プライマリ（ルート）・クラス（例えば、CIRCLE）である。その特徴が他のクラスによって継承されるクラスが、基底クラスである（例えば、CIRCLEはCIRCLE-FILL の基底クラスである）。派生クラスは、複数のクラスの特徴を継承することもできる。すなわち、派生クラスは、複数の基底クラスをもつことができる。これは、多重継承と呼ばれる。
【００１５】
派生クラスは、基底クラスを仮想継承することを指定することもできる。基底クラスの仮想継承は、仮想的な基底クラスのインスタンスが派生クラスに一つだけ存在することを意味する。例えば、以下には、２つの仮想的でない基底クラスをもった派生クラスの例が示されている。
【００１６】
0004027679.tif 000004
【００１７】
この宣言において、クラスPATTERN は、クラスCIRCLE-1およびCIRCLE-2によりクラスCIRCLEを非仮想的に二重継承する。クラスPATTERN には、２つのクラスCIRCLEというインスタンスが存在する。
【００１８】
次は、２つの仮想基底クラスを有する派生クラスの例である。
【００１９】
0004027679.tif 000005
【００２０】
派生クラスPATTERN は、クラスCIRCLE-1およびCIRCLE-2を介してクラスCIRCLEを仮想的に二重継承する。クラスCIRCLEが仮想的に二重継承されるので、派生クラスPATTERN には、クラスCIRCLEというただ一つのオブジェクトが存在することになる。クラスの派生が複雑な場合に、仮想継承が非常に有益であることが、この技術分野の専門家には分かるだろう。
【００２１】
また、クラスは、その関数メンバが仮想的であるかどうかを指定することもできる。関数メンバが仮想的であることを宣言すると、派生クラスにおいて、同じ名前と型の関数によってその関数を上書き（オーバライド）できることを意味する。以下の例では、関数drawが、クラスCIRCLEおよびCIRCLE-FILL において仮想的に宣言されている。
【００２２】
0004027679.tif 000006
【００２３】
Ｃ++言語は、ポインタ型のデータを提供する。ポインタは、メモリにおけるオブジェクトのアドレス値を保持する。ポインタによって、オブジェクトは参照される。次の文は、クラスCIRCLE型のオブジェクトへのポインタである変数c-ptr の宣言を示している。変数c-ptr は、オブジェクトｃのアドレスを保持するようにセットされる。
【００２４】
0004027679.tif 000007
【００２５】
続いて、次の文は、オブジェクトａがクラスCIRCLE型のオブジェクトであることを、オブジェクトｂがクラスCIRCLE-FILL 型のオブジェクトであることをそれぞれ宣言している。
【００２６】
0004027679.tif 000008
【００２７】
次の文は、クラスCIRCLEで定義された関数drawを参照するものである。
【００２８】
0004027679.tif 000009
【００２９】
以下の文は、クラスCIRCLE-FILL で定義された関数drawを参照するものである。
【００３０】
0004027679.tif 000010
【００３１】
次の文は、クラスCIRCLE型のオブジェクトにオブジェクトｂをキャストし、クラスCIRCLE-FILL で定義された関数drawを呼び出すものである。したがって、呼び出される仮想関数は、関数CIRCLE-FILL::draw である。
【００３２】
0004027679.tif 000011
【００３３】
オブジェクト指向型の手法を用いる利点として、オブジェクト構造体の共有が容易になるという点が挙げられる。例えば、オブジェクト指向型の手法は、混合（コンパウンド：compound）ドキュメント（コンパウンド・ドキュメント）の作成を容易にする。混合ドキュメントは、様々なコンピュータ・プログラムによって生成されたオブジェクトを含むドキュメントである（典型的には、オブジェクトとクラスのデータ・メンバのみが混合ドキュメントに記述される）。スプレッドシート・プログラムによって生成されたスプレッドシート・オブジェクトを含むワード・プロセッシング・ドキュメントは、混合ドキュメントである。ワード・プロセッシング・プログラムにより、ユーザは、ワード・プロセッシング・ドキュメント内にスプレッドシート・オブジェクト（例えば、セル）を組み込むことができる。この組み込みを可能にする一つの方法において、ワード・プロセッシング・プログラムは、組み込まれるオブジェクトのクラスの定義を用いて、一般にコンパイルされ、組み込まれたオブジェクトの関数メンバにアクセスする。したがって、ワード・プロセッシング・プログラムは、ワード・プロセッシング・ドキュメントに組み込むことができるオブジェクトの各クラスのクラス定義を用いて、コンパイルされる必要がある。新しいクラスのオブジェクトをワード・プロセッシング・ドキュメントに組み込むために、ワード・プロセッシング・プログラムは、その新しいクラスの定義を用いて再コンパイルされる必要がある。したがって、ワード・プロセッシング・プログラムの開発者によって選択されたクラスのオブジェクトだけが、組み込まれることができる。この手法を用いると、新しいクラスは、ワード・プロセッシング・プログラムの新しいリリースによりサポートされるだけである。
【００３４】
任意のクラスのオブジェクトを混合ドキュメントに組み込むことを可能にするために、インタフェースが定義される。このインタフェースは、ワード・プロセッシング・プログラムがコンパイル時にクラスのインプリメンテーション（実現ないし実現したもの）（implementation）にアクセスする必要なく、オブジェクトにアクセスできるものである。抽象クラスは、仮想関数メンバがインプリメンテーションを持たない（ピュアな）クラスである。インタフェースは、データ・メンバを持たず、その仮想関数が全てピュアである抽象クラスである。
【００３５】
次のＣ++のクラスの定義は、インタフェースの定義の例である。この例では、説明を簡単にするために、ワード・プロセッシング・プログラムは、そのドキュメントに、オブジェクトの任意のクラスではなく、スプレッドシート・オブジェクトの組み込みを許容している。インタフェースを提供するオブジェクトは、サーバ・オブジェクトである。インタフェースを使用するオブジェクトは、クライアント・オブジェクトである。オブジェクトがどのように実行されるかに関係なく、このインタフェースを提供する任意のスプレッドシート・オブジェクトを組み込むことができる。さらに、ワード・プロセッシング・プログラムのコンパイルの前後の実行の問わずに、任意のスプレッドシート・オブジェクトを組み込むことができる。
【００３６】
0004027679.tif 000012
【００３７】
スプレッドシート・プログラムの開発者は、スプレッドシート・オブジェクトをワード・プロセッシング・ドキュメントに組み込ませるために、このインタフェースのインプリメンテーションを提供する必要がある。ワード・プロセッシング・プログラムが、スプレッドシート・オブジェクトを組み込むときに、このプログラムは、スプレッドシート・オブジェクト用のインタフェースを実現（インプリメント）するコードにアクセスする必要がある。コードにアクセスするために、ユニークなクラス識別子が各インプリメンテーションに与えられる。例えば、マイクロソフト社によって開発されたスプレッドシート・オブジェクトは、“MSSpreadsheet ”というクラス識別子をもつ。一方、他の会社によって開発されたスプレッドシート・オブジェクトは、“LTSSpreadsheet”というクラス識別子をもつ。クラスを実現するコードに各クラス識別子をマップする、各コンピュータ・システムにおけるパーシステント・レジストリ（persistent registry ）が保持される。一般に、スプレッドシート・プログラムがコンピュータ・システムにインストールされるときに、そのスプレッドシート・オブジェクトのクラスを利用できるようにパーシステント・レジストリが更新される。スプレッドシートの開発者が、インタフェースによって定義される全ての関数メンバを実現し、パーシステント・レジストリが保持される限り、ワード・プロセッシング・プログラムは、開発者のスプレッドシート・オブジェクトをワード・プロセッシング・ドキュメントに組み込むことができる。
【００３８】
しかしながら、様々なスプレッドシートの開発者が、一定の関数メンバの実現のみを望んでいる。例えば、あるスプレッドシートの開発者は、データベースのサポートを実現したくないが、全ての他の関数メンバをサポートしたいかもしれない。スプレッドシートの開発者にいくつかの関数メンバのみをサポートさせ、なおもオブジェクトの組み込みを可能とするために、スプレッドシート・オブジェクト用の複数のインタフェースが定義される。例えば、インタフェースIData およびIBasicSpreadsheet が、次のように、スプレッドシート・オブジェクト用に定義される。各スプレッドシートの開発者は、IBasicSpreadsheet インタフェースおよびオプションとしてIData インタフェースを実現する。
【００３９】
0004027679.tif 000013
【００４０】
実行時に、ワード・プロセッシング・プログラム（またはこのインタフェースの任意の他のクライアント）は、組み込まれるスプレッドシート・オブジェクトがIData インタフェースをサポートするかどうかを判定する必要がある。この判定を行うために、どのインタフェースがオブジェクト用に実現されるているかを示す関数メンバを有する（全スプレッドシート・オブジェクトが実現する）もう一つのインタフェースが、定義される。このインタフェースは、IUnknownと名付けられ（unknown インタフェースまたはオブジェクト管理インタフェースとして参照され）、次のように定義される。
【００４１】
0004027679.tif 000014
【００４２】
IUnknownインタフェースは、関数メンバ（メソッド）QueryInterfaceを定義する。メソッドQueryInterfaceは、インタフェース識別子（例えば、“IData ”）をパラメータiid （タイプREFIIDのパラメータ）に渡し、このメソッドが呼び出されるオブジェクトの識別されたインタフェースのインプリメンテーションへのポインタを、パラメータppv に返す。このオブジェクトがインタフェースをサポートしないならば、このメソッドはフォールス（false ：偽）を返す（タイプHRESULT は予め定められたステータスを示し、タイプULONG はアンサインド（unsigned：符号なし型）・ロング・インテジャ（整数）を示す) 。
【００４３】
0004027679.tif 000015
【００４４】
コード・テーブル1Aは、クラスIUnknownを継承するクラスXXのメソッドQueryInterfaceの典型的なインプリメンテーションのためのＣ++の擬似コードを含んでいる。スプレッドシート・オブジェクトがIData インタフェースをサポートする場合に、QueryInterfaceは、switch文内に適切なケース・ラベルを含む。変数pIBasicSpreadsheetおよびpIDataは、IBasicSpreadsheet およびIData インタフェースの仮想関数テーブルへのポインタをそれぞれ指すものである。インタフェースへのポインタが返されると、メソッドQueryInterfaceは、メソッドAddRef（後述）を呼び出し、クラスXXのオブジェクトのリファレンス・カウンタをインクリメントする。
【００４５】
0004027679.tif 000016
【００４６】
インタフェースIUnknownは、メソッドAddRefおよびRelease も定義する。これらのメソッドは、リファレンス・カウントを実現するために使用される。インタフェースのリファレンスが新しく生成されるたびに、メソッドAddRefが呼び出され、そのオブジェクトのリファレンス・カウントがインクリメントされる。リファレンスがもはや必要なくなると、メソッドRelease が呼び出され、そのオブジェクトのリファレンス・カウントがディクリメントされる。リファレンス・カウントが零になると、そのオブジェクトの割当が解除される。コード・テーブル1Bは、クラスIUnknownを継承するクラスXXのメソッドAddRefおよびRelease の典型的なインプリメンテーションのためのＣ++の擬似コードを含んでいる。
【００４７】
IData インタフェースおよびIBasicSpreadsheet インタフェースは、IUnknownインタフェースを継承する。次の定義は、IUnknownインタフェースを使用を示している。
【００４８】
0004027679.tif 000017
【００４９】
図２は、スプレッドシート・オブジェクトのデータ構造のサンプルを示すブロック図である。スプレッドシート・オブジェクトは、オブジェクト・データ構造体1B01、IBasicSpreadsheet インタフェース・データ構造体1B03、IData インタフェース・データ構造体1B04、仮想関数テーブル1B02、1B05、1B06、およびメソッド1B07〜1B21を有する。オブジェクト・データ構造体1B01は、仮想関数テーブル1B02へのポインタおよびIBasicSpreadsheet とIData インタフェースへのポインタを含んでいる。仮想関数テーブル1B02の各エントリは、IUnknownインタフェースのメソッドへのポインタを有する。IBasicインタフェース・データ構造体1B03は、仮想関数テーブル1B05へのポインタを有する。仮想関数テーブル1B05の各エントリは、IBasicSpreadsheet インタフェースのメソッドへのポインタを有する。IData インタフェース・データ構造体1B04は、仮想関数テーブル1B06へのポインタを有する。仮想関数テーブル1B06の各エントリは、IData インタフェースのメソッドへのポインタを有する。IBasicSpreadsheet およびIData インタフェースは、IUnknownインタフェースを継承するので、各仮想関数テーブル1B05および1B06は、メソッドQueryInterface、AddRefおよびRelease へのポインタを含んでいる。続いて、オブジェクト・データ構造体は、そのオブジェクトをアクセスすインタフェースをもったラベル1B22の形により表されている。
【００５０】
次の擬似コードは、スプレッドシート・オブジェクトがIData インタフェースをサポートするかどうかを、ワード・プロセッシング・プログラムがどのように判定するかを示している。
【００５１】
0004027679.tif 000018
【００５２】
ポインタpIBasicSpreadsheetは、このオブジェクトのIBasicSpreadsheet インタフェースへのポインタである。このオブジェクトがIData インタフェースをサポートするならば、メソッドQueryInterfaceは、ポインタpIDataをIData データ構造体を指すようにセットし、値S-OKを返す。
【００５３】
一般に、オブジェクトは、変数宣言または演算子“new ”によって生成することができる（オブジェクトのインスタンスがメモリに生成される）。しかしながら、この両方の生成手法は、コンパイル時にクラス定義を必要とする。ワード・プロセッシング・プログラムが実行時にスプレッドシート・オブジェクトを生成できる異なる手法が、必要とされる。一つの手法は、以下に定義されるグローバル関数CreateInstanceXXを提供する。
【００５４】
0004027679.tif 000019
【００５５】
メソッドCreateInstanceXX（クラス・ファクトリとして知られている）は、クラスXXのオブジェクトを生成し、パラメータiid によって示されるオブジェクトのインタフェースへのポインタppv を返す。
【００５６】
【発明の開示】
この発明の目的は、コンポーネント間のインタラクションを管理する方法およびシステムを提供することにある。
【００５７】
この発明の目的は、単一問題領域（シングル・プロブレム・ドメイン）に限定されない方法およびシステムを提供することにある。
【００５８】
この発明の目的は、全てのコンポーネントが共有できるコンポーネント間のインタラクションを管理する方法およびシステムを提供することにある。
【００５９】
この発明の目的は、オーバヘッドを最小にする方法で、コンポーネント間のインタラクションを管理する方法およびシステムを提供することにある。
【００６０】
この発明の他の目的は、実行中に継続的にコンポーネントを記憶するメソッドおよびシステムを提供することにある。
【００６１】
この発明についての以下の詳細な説明により明らかになる、これらの目的および他の目的は、サーバ・コンポーネントによって実現されるインタフェースへのクライアント・コンポーネントの接続を管理するメソッドおよびシステムによって達成される。好ましい実施例において、ユーザ・コンポーネントは、インタフェースのインプリメンテーションおよびインタフェースのディスクリプタを提供する。コンポーネント・マネージャは、ユーザ・コンポーネントをそれ自身に統合し、サーバ・コンポーネントを形成する。クライアントが、インタフェースへの接続を要求すると、コンポーネント・マネージャは、ユーザ・コンポーネントからインタフェースへのリファレンスを検索し、クライアント・コンポーネントへこのリファレンスを送る。好ましい実施例において、コンポーネント・マネージャは、インタフェースを介して接続されるクライアント・コンポーネントを追跡する。また、ユーザ・コンポーネントは、多重インタフェースも、コンポーネント・マネージャが追跡するクライアント・コンポーネントに提供する。
【００６２】
【実施例】
この発明は、コンポーネント間のインタフェースの共有を管理する方法およびシステムを提供する。好ましい実施例では、ユーザ・コンポーネントは、インタフェースのインプリメンテーションおよびインタフェースの記述を提供する。コンポーネント・マネージャは、ユーザ・コンポーネントをそれ自身に統合し、サーバ・コンポーネントを形成する。クライアント・コンポーネントがインタフェースへの接続要求を出すと、コンポーネント・マネージャは、ユーザ・コンポーネントからこのインタフェースへのリファレンスを検索し、このリファレンスをクライアント・コンポーネントに送る。この実施例において、コンポーネント・マネージャは、インタフェースを介して接続されたクライアント・コンポーネントを追跡する。ユーザ・コンポーネントは、コンポーネント・マネージャが追跡するクライアント・コンポーネントへ複数のインタフェースを提供することもある。
【００６３】
コンポーネントは、他の様々なコンポーネントにサービスを提供する。これらのサービスは、そのコンポーネントが実現するインタフェースを介して提供される。インタフェースを提供するコンポーネントはサーバ・コンポーネント（サーバ）と呼ばれ、インタフェースのサービスを使用するコンポーネントはクライアント・コンポーネント（クライアント）と呼ばれる。クライアント・コンポーネントには、インタフェースへのポインタが渡され、クライアント・コンポーネントは、そのインタフェースのメソッドを呼び出すことによりサービスを要求する。場合によっては、サーバ・コンポーネントが、クライアント・コンポーネントに、あるイベントを直接に通知したい場合もあり、また、サーバ・コンポーネントが、そのクライアント・コンポーネントから情報を取り出したい場合もある。これらの場合に、クライアント・コンポーネントは、リバース・インタフェースと呼ばれるインタフェースを、サーバ・コンポーネントに与える。サーバ・コンポーネントは、このリバース・コンポーネントにポインタを与えられ、リバース・インタフェースのメソッドを呼び出すことによりサービスを要求する。一般に、サーバ・コンポーネントは、ある特定のインタフェースを提供し、ある特定のリバース・インタフェースを介してクライアント・コンポーネントのサービスを要求する。この特定のインタフェースおよびリバース・インタフェースの組合せは、プロトコルとして知られている。プロトコルは、一方向または双方向のいずれであってもよい。一方向プロトコルでは、クライアント・コンポーネントはリバース・インタフェースを提供しない。したがって、サービスは、サーバ・コンポーネントによってのみ提供される。双方向プロトコルでは、クライアント・コンポーネントとサーバ・コンポーネントのいずれもがインタフェースを提供する。したがって、サービスは、サーバ・コンポーネントとクライアント・コンポーネントの双方から提供される。サーバからクライアントへインタフェースのポインタを渡し、プロトコルが双方向ならばクライアントからサーバへリバース・インタフェースのポインタを渡すことにより、サーバ・コンポーネントとクライアント・コンポーネントとの間のプロトコルを介して、接続（コネクション）が確立される（インタフェースとコンポーネントの詳細は、「OLE 2.0 設計仕様書」に示されている）。
【００６４】
図３は、一方向接続を示すブロック図である。サーバ101 が、IServer インタフェースをクライアント102 に提供する。クライアント102 は、IServer インタフェースへのポインタを有する。図４は、双方向接続を示すブロック図である。サーバ111 がIServer インタフェースを提供し、クライアントがICientインタフェースを提供する。サーバ111 は、ICientインタフェースへのポインタを有し、クライアント112 は、IServer インタフェースへのポインタを有する。サーバ111 およびクライアント112 は、IServer/IClient プロトコルによって接続（コネクト）される。
【００６５】
双方向プロトコルの場合に、サーバ・コンポーネントとクライアント・コンポーネントの双方が、他方へサービスを提供する。したがって、サービスの点において、各コンポーネントを、サーバとクライアントの両方とみなすことができる。サポートするプロトコルを指定することにより、コンポーネントは、それが提供するサービスとクライアント・コンポーネントに要求するサービスとを識別している。以下では、プロトコルの一方のインタフェースが、ジャック・インタフェースと呼ばれ、他方のインタフェースがプラグ・インタフェースと呼ばれる。ジャック・インタフェースを提供するコンポーネントは、プロトコルのジャック接続を提供すると言われ、プラグ・インタフェースを提供するコンポーネントは、プロトコルのプラグ接続を提供すると言われる。
【００６６】
コンポーネントは、プロトコル用に多重接続を確立することもできる。図５は、プロトコルによる多重接続を示すブロック図である。サーバ121 は、IServer インタフェースを提供し、クライアント122 および123 のそれぞれは、IClient インタフェースを提供する。サーバ121 は、各IClient インタフェースへのポインタを有し、クライアント122 および123 のそれぞれは、IServer インタフェースへのポインタを有する。サーバ121 は、このサーバが各クライアントの状態情報を保持し、サービスを要求するクライアントを識別できるように、各クライアントに異なったポインタを与える。
【００６７】
また、コンポーネントは、多重プロトコルをサポートし、多重接続を各プロトコル用に確立することもできる。図６は、多重プロトコルをサポートするコンポーネントを示すブロック図である。サーバ131 は、IServerA/IClientA プロトコルおよびIServerB/IClientB プロトコルをサポートする。クライアント132 および133 は、IServerA/IClientA プロトコルにより接続され、クライアント134 および135 は、IServerB/IClientB プロトコルにより接続される。
【００６８】
この発明は、コンポーネント間接続の確立を制御する方法およびシステムを提供する。この実施例において、プロトコルのインタフェースのインプリメンテーションを提供するコンポーネントは、ユーザ・コンポーネントである。ユーザ・コンポーネントは、コンポーネント・マネージャ・オブジェクトと統合され、コンポーネント・オブジェクトを形成する。コンポーネント・マネージャ・オブジェクト（コンポーネント・マネージャ）は、ユーザ・コンポーネントによって提供されるインタフェースへの接続の確立と追跡を管理する。コンポーネント・マネージャは、領域独立方式で確立することができる接続を介してインタフェースを提供する。
【００６９】
図７は、好ましいコンポーネントの構造を示すブロック図である。コンポーネント・オブジェクト201 は、コンポーネント・マネージャ202 、ユーザ・コンポーネント203 およびコネクタ・オブジェクト204 （コネクタ）を備えている。コンポーネント・マネージャ202 は、ユーザ・コンポーネント203 が提供するプロトコルによって、コンポーネント201 の他のコンポーネントへの接続を管理する。コンポーネント・マネージャは、コンポーネントの接続を制御するIComponentManager インタフェースを提供する。ユーザ・コンポーネント103 は、インタフェースの領域特有の振る舞いを提供する。コネクタ104 は、コンポーネント・マネージャによって生成され、接続状態を追跡し、接続を制御するIConnectorインタフェースを提供する。
【００７０】
図８は、コンポーネント・マネージャの好ましいデータ構造を示すブロック図である。コンポーネント211 は、コンポーネント・マネージャ212 およびコネクタ・ディスクリプタ（記述子）・エントリ214 のリンク・リスト213 （DEList）を備えている。各ディスクリプタ（記述子）・エントリは、コネクタ・エントリ214 のリンク・リスト（CEList）およびコネクタ・ディスクリプタ215 をポイントする。コンポーネント・マネージャは、ユーザ・コンポーネントによって提供される各プロトコル用に一つのディスクリプタ・エントリを生成する。コンポーネント・マネージャは、与えられるプロトコルの各接続用にコネクタ・エントリを生成する。各コネクタ・ディスクリプタは、ユーザ・コンポーネントによって提供されるもので、ユーザ・コンポーネントによって提供される一つのプロトコルを記述するものである。コンポーネント・マネージャ212 は、ユーザ・コンポーネント216 およびコンポーネント・ディスクリプタ217 をポイントする。コンポーネント・ディスクリプタは、ユーザ・コンポーネントによって提供されるもので、そのコンポーネントの属性を記述するものである。
【００７１】
この発明は、コンポーネントの接続に使用できる様々な関数を提供する。一実施例において、コンポーネント・マネージャが提供するIComponentインタフェースによって、これらの関数を提供することができる。基本関数は、関数ComponentNewConnector である。この関数は、指定されたプロトコル用のコネクタを「成形する」（extrude ）。コネクタを成形するために、コンポーネント・マネージャは、指定されたプロトコルの新しいコネクタ・エントリを生成し、この新しいコネクタ・エントリのIConnectorインタフェースへのポインタを返す。プロトコルのプラグおよびジャック・コネクタの両方が成形されると、これらを関数ComponentConnectと接続することができる。関数ComponentConnectは、リバース・インタフェースへのポインタを各ユーザ・コンポーネントに格納し、接続を追跡するために状態情報を初期化する。図９は、この実施例における２つのコンポーネント間の接続例を示すブロック図である。コンポーネント301 および311 は、IUSERJACK/IUSERPLUG プロトコルによって接続される。コンポーネント301 は、コンポーネント・マネージャ302 、およびIUSERJACK インタフェースを記述するディスクリプタ・エントリ303 を備えている。コンポーネント301 は、IUSERJACK インタフェース用のジャック・コネクタ304 を成形するように要求される。コンポーネント・マネージャ302 は、IUSERJACK インタフェース・エントリ303 のディスクリプタ・エントリを検索し、ジャック・コネクタ304 を生成する。ジャック・コネクタ304 は、ユーザ・コンポーネント305 によって提供されるIUSERJACK インタフェースへのポインタを備えている。同様にして、コンポーネント311 は、コンポーネント・マネージャ312 、およびIUSERPLUG インタフェースを記述するディスクリプタ・エントリ313 を備えている。コンポーネント311 は、IUSERPLUG インタフェース用のプラグ・コネクタ314 を成形するように要求される。コンポーネント・マネージャ312 は、IUSERPLUG インタフェース・エントリのディスクリプタ・エントリを検索し、プラク・コネクタ314 を生成する。プラグ・コネクタ314 は、コンポーネント315 によって提供されるIUSERPLUG インタフェースへのポインタを備えている。
【００７２】
ジャック・コネクタ304 とプラグ・コネクタ314 が一度成形されると、これらのコネクタを介してコンポーネントを接続することができる。一実施例において、関数ComponentConnectには、ジャック・コネクタ304 およびプラグ・コネクタ314 の両方が、それらのIConnectorインタフェースへのポインタを渡すことによって渡される。関数ComponentConnectは、ジャック・コネクタ304 およびユーザ・コンポーネント305 を、IUSERPLUG インタフェースをポイントするようにセットする（破線で示す）。同様にして、関数ComponentConnectは、プラグ・コネクタ314 およびユーザ・コンポーネント315 を、IUSERJACK インタフェースをポイントするようにセットする（破線で示す）。ユーザ・コンポーネント305 および315 は、それらのリバース・インタフェースのメソッドに、リバース・インタフェース・ポインタを介してアクセスすることができる。
【００７３】
0004027679.tif 000020
【００７４】
0004027679.tif 000021
【００７５】
コンポーネントの生成中に、ユーザ・コンポーネントは、コンポーネント・マネージャにコンポーネント・ディスクリプタを提供する。コード・テーブル2Aは、コンポーネント・ディスクリプタのデータ構造を含んでいる。コンポーネント・ディスクリプタは、コネクタ・ディスクリプタの配列へのポインタ（pConnDesc ）、この配列のエントリ数のカウント（cConnectors ）、ユーザ・コンポーネント内の生成コールバック・ルーチンへのポインタ（*Create ）およびフラグ（flag）を備えている。コンポーネント・マネージャは、コンポーネント生成中に、生成コールバック・ルーチンを呼び出す。フラグは、後述するように、コンポーネントの様々な属性を表す。
【００７６】
各コネクタ・ディスクリプタは、ユーザ・コンポーネントによって提供されるインタフェースのインタフェースid（piid）、対応するリバース・インタフェースid（piidm ）、インスタンス名（iname ）、コネクタの最大数（cMaxConnectors）、ユーザ・コンポーネントのリバース・インタフェース・ポインタのオフセット（RevIfacePtrOff）、ユーザ・コンポーネント内の様々なコールバック・ルーチン、およびフラグ（flag）を含んでいる。コード・テーブル2Bは、コネクタ・ディスクリプタのデータ構造を示している。インタフェースidは、ユーザ・コンポーネントが提供するプロトコルのインタフェースを指定する。リバース・インタフェースidは、ユーザ・コンポーネントがコンポーネントに接続されたものによって提供される予定のインタフェースを指定する。インスタンス名は、ユーザ・コンポーネントによって提供される同じプロトコルの複数のインプリメンテーションを区別するために使用される。コネクタの最大数は、一時に成形できる記述されたプロトコルのコネクタの最大数を示す。ユーザ・コンポーネント内のリバース・インタフェース・ポインタのオフセットは、提供されるインタフェース・ポインタに対する相対的なリバース・インタフェース・ポインタの位置をコンポーネント・マネージャに示すものである。コンポーネント・マネージャは、様々なコールバック・ルーチンを介して接続状態の変化をユーザ・コンポーネントに報告する。この実施例においては、コネクタが成形、接続、接続解除、および消去されることが、コールバック・ルーチンによってユーザ・コンポーネントに報告される。フラグは、後述するようにコネクタの様々な属性を記述するものである。
【００７７】
この発明は、コネクタを生成し、コンポーネント間の接続を確立する様々な関数を提供する。これらの関数には、新しいコネクタを生成する関数（ComponentNewConnector ）、２つのコネクタを接続する関数（ComponentConnect）、２つのコネクタを接続解除する関数（CoponentDisconnect）、およびコネクタを消去する関数（ComponentDeleteConnector）が含まれる。さらに、この実施例は、コネクタ・ディスクリプタとコネクタを列挙する関数も提供する。
【００７８】
また、この発明は、コンポーネント・マネージャを初期化する関数（ComponentInit ）を提供する。ユーザ・コンポーネントが生成されると、このユーザ・コンポーネントのクラス・ファクトリは、関数ComponentInit を呼び出す。この関数には、このユーザ・コンポーネントのクラスidおよびコネクタ・ディスクリプタの配列をポイントするコンポーネント・ディスクリプタが、引数として渡される。この関数は、コンポーネント・マネージャ・オブジェクトを生成し、ユーザ・コンポーネントを統合する（オブジェクトの統合については、1992年12月24日に出願された米国特許出願第07/996,552号の「オブジェクトを統合する方法およびシステム」（“METHOD AND SYSTEM FOR AGGREGATING OBJECTS ”）に示されている）。また、この関数は、コネクタ・ディスクリプタの配列に対応するDEListを生成する。関数ComponentInit の好ましいプロトタイプを以下に示す。
【００７９】
0004027679.tif 000022
【００８０】
パラメータpUnkOuter は、制御するIUnknownインタフェースをポイントする。パラメータriidは、パラメータppIUnkに返されるインタフェースのインタフェースidである。パラメータpCompDesc は、コンポーネント・ディスクリプタへのポインタである。パラメータclsid は、ユーザ・コンポーネントのクラスidである。図10は、関数ComponentInit のフローチャートである。ステップ401 において、この関数は、コンポーネント・マネージャ・オブジェクトを割り当てる。ステップ402 において、関数は、DEListを空（エンプティ）にセットすることにより、コンポーネント・マネージャを初期化する。ステップ403 において、関数は、ディスクリプタ・エントリを生成し、コネクタ・ディスクリプタの配列内に指定された各コネクタ・ディスクリプタに対応するDEListにこのディスクリプタ・エントリを加える。ステップ404 〜407 において、関数は、パラメータpUnkOuter がNULLでない場合に、コンポーネントを統合オブジェクトに統合する。ステップ404 において、関数は、コンポーネント・マネージャのpUnkOuter をパラメータpUnkOuter と等しくなるようにセットする。ステップ405 において、パラメータpUnkOuter がNULLに等しいならば、関数はステップ406 に進み、そうでなければステップ407 に進む。ステップ406 では、関数は、コンポーネント・マネージャのpUnkOuter を、コンポーネント・マネージャのIUnknownインタフェースをポイントするようにセットし、ステップ408 に進む。ステップ407 で、要求されたインタフェースが、IUnknownインタフェースでない場合には、関数の処理は終了し、リターンする。ステップ408 において、関数は、コンポーネント・ディスクリプタに指定されたユーザ・コンポーネントの生成コールバックを呼び出す。生成コールバックは、ユーザ・コンポーネントを生成し、これをコンポーネントに統合する。関数は、コンポーネント・マネージャをユーザ・コンポーネントをポイントするようにセットする。ステップ409 〜414 で、関数は、パラメータriidによって示されるインタフェースへのポインタを検索する。ステップ409 で、パラメータpUnkOuter がNULLならば、関数はステップ413 に進み、そうでなければステップ411 に進む。ステップ411 において、関数は、要求されたインタフェースをIUnknownインタフェースにセットする。ステップ412 で、関数は、コンポーネント・マネージャのリファレンス・カウントをインクリメントし、リターンする。ステップ413 で、関数は、制御するIUnknownのメソッドQueryInterfaceを呼び出すことにより、要求されたインタフェースを検索する。ステップ414 では、関数は要求されたインタフェースを返す。
【００８１】
コンポーネントが、生成され、初期化されると、コネクタが成形され、接続される。関数ComponentNewConnector は、指定されたインタフェースidのコネクタを生成し、このコネクタのIConnectorインタフェースにポインタを返す。関数ComponentNewConnector の好ましいプロトタイプを以下に示す。
【００８２】
0004027679.tif 000023
【００８３】
パラメータpCM は、このコンポーネントのコンポーネント・マネージャをポイントするものである。パラメータriidは、生成されるコネクタのプロトコルを記述するディスクリプタ・エントリのインタフェースidであり、パラメータpName は、このディスクリプタ・エントリのインスタンス名である。パラメータppIConnectorは、生成されたコネクタへのポインタである。このコネクタは、ユーザ・コンポーネントによって提供されるインタフェースへのポインタを含んでいる。この関数は、ディスクリプタ・エントリの生成コールバックを呼び出し、インタフェースのポインタを取り出す。この実施例において、関数ＣomponentNewConnectorは、渡されたコンポーネント・マネージャのIComponentJackインタフェースのメソッドNewConnectorを呼び出し、新しいコネクタを生成する。メソッドNewConnectorについては、後述する。
【００８４】
接続が、関数ComponentConnectを呼び出すことにより確立される。この関数には、２つのコネクタへのポインタ（IConnectorインタフェース）が渡される。この関数は、どのコネクタがプラグかジャックかを判定し、それらが、リバース・インタフェースのプロトコルを表すことを保証する。続いて、関数は、ジャック・コネクタのメソッドConnect およびプラグ・コネクタのメソッドConnectAndNotifyを呼び出す。プラグ・コネクタのメソッドConnectAndNotifyがリターンするときに、ジャック・コネクタのメソッドConnect が、このジャック・コネクタに通知される指示をリターンするならば、関数は、ジャック・コネクタのメソッドNotifyDidConnectを呼び出す。いずれかのコンポーネントのユーザ・コンポーネントに、コネクタ・ディスクリプタに指定された接続コールバックを介して報告してもよい。規約により、ジャック・コネクタのユーザ・コンポーネントに通知する前に、プラグ・コネクタのユーザ・コンポーネントには、コンポーネント・マネージャによって接続が通知される。したがって、プラグ・コネクタを、初期化に特有の接続を実行するのに使用することができる。関数ComponentConnectの好ましいプロトタイプを以下に示す。
【００８５】
0004027679.tif 000024
【００８６】
パラメータpIConnector1およびpIConnector2は、接続されるコネクタをポイントする。図11は、関数ComponentConnectのフローチャートである。ステップ501 において、この関数は、どのコネクタがプラグであるかを判定する。ステップ502 において、コネクタがリバース・インタフェースのプロトコルを表すものでないならば、関数はエラーを返す。ステップ503 において、関数は、プラグ・コネクタのポインタをパラメータとして渡す、ジャック・コネクタのメソッドConnect を呼び出す。メソッドConnect は、プラグ・コネクタの接続完了後に、ジャック・コネクタに通知するかどうかを示すフラグを返す。ステップ504 で、関数は、ジャック・コネクタへのポインタをパラメータとして渡す、プラグ・コネクタのメソッドConnectAndNotifyを呼び出す。ステップ505 で、ジャック・コネクタに通知しないならば、関数はリターンする。ステップ506 で、関数は、ジャック・コネクタのメソッドNotifyDidConnectwo呼び出し、リターンする。接続が一度確立されると、ユーザ・コンポーネントは、リバース・インタフェース・ポインタを使用し、インタフェースのメソッドにアクセスすることができる。
【００８７】
接続は、関数ComponentDisconnect を呼び出すことにより解除される。関数ComponentDisconnect は、渡されたコンポーネントが接続されていることを確認し、どのコネクタがジャック・コネクタであり、プラグ・コネクタであるかを決定する。続いて、関数は、プラグ・コネクタのメソッドNotifyWillDisconnect、ジャック・コネクタのメソッドNotifyAndDisconnect およびプラグ・コネクタのメソッドDisconnectを呼び出す。関数ComponentDisconnect の好ましいプロトタイプを以下に示す。
【００８８】
0004027679.tif 000025
【００８９】
パラメータpIConnector1およびpIConnector2は、接続解除されるコネクタのIConnectorインタフェースをポイントする。図12は、関数ComponentDisconnect のフローチャートである。ステップ601 において、渡されたコネクタが接続されていないならば、この関数はエラーを返す。ステップ602 では、関数は、コネクタがプラグかジャックかを判定する。ステップ603 で、関数はプラグ・コネクタのメソッドNotifyWillDisconnectを呼び出す。ステップ604 で、関数はジャック・コネクタのメソッドNotifyAndDisconnect を呼び出す。ステップ605 で、関数は、プラグ・コネクタのメソッドDisconnectを呼び出す。ステップ606 で、関数は、プラグおよびジャック・コネクタをリリース（解放）し、リターンする。
【００９０】
0004027679.tif 000026
【００９１】
コード・テーブル３は、IJack およびIPlug インタフェースのインタフェース・ディスクリプタを含んでいる。ジャック・コネクタはIJack インタフェースを提供し、プラグ・コネクタはIPlug インタフェースを提供する。これらのインタフェースのメソッドは、コンポーネント間の接続の確立に使用される。
【００９２】
図13は、IJack インタフェースのメソッドConnect のフローチャートである。このメソッドには、プラグへのポインタ（pIP ）が渡される。メソッドは、このジャック（「この」ポインタによって示される）をそのプラグに接続する。メソッドは、ジャックおよびプラグのインタフェースの識別子（pJackIIDおよびpPlugIID）、このジャックの記述フラグ（pCDflag ）、ならびに接続完了時にこのジャックに通知するかどうかを示すフラグ（pFlag ）を返す。ステップ701 で、このジャックが接続中であるか接続されているものならば、メソッドはエラーを返す。ステップ702 で、このジャックのユーザ・コンポーネントが、接続コールバックによって示される通知を要求するものならば、メソッドはステップ703 に進み、そうでなければステップ704 に進む。ステップ703 で、メソッドは、このジャックを接続中であることを示すようにセットする。ステップ704 で、メソッドは、このジャックを接続されたものであることを示すようにセットする。ステップ705 では、メソッドは、渡されたプラグから、プラグ・インタフェースへのポインタを取り出す。ステップ706 において、メソッドは、このジャックのリバース・インタフェース・ポインタをセットする。ステップ707 で、メソッドは、ユーザ・コンポーネントのリバース・インタフェース・ポインタをセットし、リターンする。
【００９３】
図14は、IJack インタフェースのメソッドNotifyDidConnectのフローチャートである。このメソッドは、ユーザ・コンポーネントに接続を通知する。ステップ801 で、このジャックが接続中でないないならば、メソッドはエラーを返す。ステップ802 で、メソッドは、このジャックを、接続されたものであり接続中でないことを示すようにセットする。ステップ803 で、メソッドは、このジャックのディスクリプタ・エントリによって示されるユーザ・コンポーネントの接続コールバックを起動し、リターンする。
【００９４】
図15は、IJack インタフェースのメソッドNotifyAndDisconnect のフローチャートである。ステップ901 において、このジャックが接続されたものでない場合に、メソッドはエラーを返す。ステップ902 で、ユーザ・コンポーネントが接続解除を通知されるものであるならば、メソッドは、接続解除コールバックをステップ903 で呼び出す。ステップ904 で、メソッドは、このジャックを、接続されていず、かつ、接続中でないことを示すようにセットする。ステップ905 で、メソッドは、プラグ・インタフェースをリリースし、リターンする。
【００９５】
図16は、IJack インタフェースのメソッドDisconnectのフローチャートである。ステップ1001において、このジャックが接続されたものでない、または、接続中のものでないならば、メソッドはエラーを返す。ステップ1002で、メソッドは、このジャックを、接続されいず、かつ、接続中でないことを示すようにセットする。ステップ1003において、メソッドは、プラグ・インタフェースをリリースし、リターンする。
【００９６】
図17は、IPlug インタフェースのメソッドConnectAndNotifyのフローチャートである。ステップ1101において、このプラグが既に接続されているならば、メソッドはエラーを返す。ステップ1102で、メソッドは、ジャック・インタフェースに接続されたものへのポインタを取り出す。ステップ1103で、メソッドは、このプラグのリバース・インタフェース・ポインタを、ジャック・インタフェースをポイントするようにセットする。ステップ1104で、メソッドは、ユーザ・コンポーネントのリバース・インタフェース・ポインタを、ジャック・インタフェースをポイントするようにセットする。ステップ1105で、ユーザ・コンポーネントが接続を通知されるものならば、メソッドは、このプラグの接続コールバックをステップ1106で呼び出す。続いて、メソッドはリターンする。
【００９７】
図18は、IPlug インタフェースのメソッドNotifyWillDisconnectのフローチャートである。ステップ1201で、このプラグが接続されていないならば、メソッドはエラーを返す。ステップ1202で、ユーザ・コンポーネントが接続解除を通知されるものならば、メソッドは、接続解除コールバックをステップ1203で起動する。ステップ1204で、メソッドは、このプラグを、接続されていず、かつ、接続解除中であることを示すようにセットする。
【００９８】
図19は、IPlug インタフェースのメソッドDisconnectのフローチャートである。ステップ1301で、このプラグが接続解除中でないならば、メソッドはエラーを返す。ステップ1302で、メソッドは、ジャック・インタフェースをリリースする。ステップ1303で、メソッドは、このプラグを、接続されていず、かつ、接続解除中でないことを示すようにセットし、リターンする。
【００９９】
0004027679.tif 000027
【０１００】
コンポーネント・マネージャは、コンポーネント間の接続管理に使用する様々なインタフェースを提供する。コード・テーブル４は、IComponentJackインタフェースを含んでいる。このインタフェースは、４つのメソッドを定義する。最初の２つのメソッドEnumerateDescriptorsおよびEnumerateConnectors は、コネクタ・ディスクリプタおよびコネクタを列挙する機構を提供する。これらのメソッドは、列挙インタフェースへのポインタを返す。列挙インタフェースは、コネクタ・ディスクリプタまたはコネクタを連続的に取り出すのに使用できるメソッドNextを有する。メソッドEnumerateDescriptorsは、各コネクタ・ディスクリプタを列挙する。このメソッドには、インタフェースid、インスタンス名およびフラグが渡される。このメソッドは、全コネクタ・ディスクリプタ、または渡されたフラグに基づくインタフェースidもしくはインスタンス名に合致するコネクタ・ディスクリプタのみの列挙インタフェースへのポインタを返す。メソッドEnumerateConnectors は、指定されたコネクタ・ディスクリプタの成形された各コネクタを列挙する。このメソッドは、コネクタ・ディスクリプタを指定するインタフェースidおよびインスタンス名を渡され、列挙インタフェースへのポインタを返す。
【０１０１】
IComponentJackインタフェースのメソッドNewConncetorは、指定されたコネクタ・ディスクリプタ用のコネクタを成形し、そのコネクタへのポインタを返す。このメソッドには、コネクタ・ディスクリプタのインタフェースid（DescIID ）およびインスタンス名（lpszName）が渡される。図20は、IComponentJackインタフェースのメソッドNewConnectorのフローチャートである。ステップ1401で、メソッドは、渡されたインタフェースidおよびインスタンス名に対応するディスクリプタ・エントリを選択する。ステップ1402で、ディスクリプタ・エントリが選択されていないならば、メソッドはエラーを返す。ステップ1403で、メソッドは、選択されたディスクリプタ・エントリ用のコネクタ・エントリを成形し、リターンする。メソッドは、選択されたディスクリプタ・エントリのメソッドExtrude を呼び出す。IComponentJackインタフェースのメソッドDeleteConnector は、類似の方法で、成形されたコネクタを消去する機能をもつ。この実施例において、ディスクリプタ・エントリは状態情報を備えている。この状態情報には、コネクタ・ディスクリプタへのポインタ、このディスクリプタ・エントリ用に成形することができるコネクタの最大数、現在成形されているコネクタ数、CEListへのポインタ、そのコネクタ用にユニークな識別子を生成するための接続idジェネレータ、およびディスクリプタ・エントリの状態を保持するフラグ・フィールドが含まれる。後述するように、ディスクリプタ・エントリの状態は、固有、投射または投射されたものにすることができる。
【０１０２】
0004027679.tif 000028
【０１０３】
コード・テーブル５は、IDescriptorEntryインタフェースを示している。このインタフェースは、新しく生成されたコネクタ・エントリへのポインタを返すメソッドExtrude を定義する。このメソッドには、出現するコンポーネントへのポインタ（pICManifesting）（後述）、フラグ（CEflag）およびユーザ・コンポーネントへのポインタ（pComponent）が渡され、メソッドは新しく生成されたコネクタへのポインタ（ppIConector ）を返す。図21は、IDescriptorEntryインタフェースのメソッドExtrude のフローチャートである。ステップ1501で、コネクタ・ディスクリプタの最大数のコネクタがすでに成形されているならば、メソッドはエラーを返す。ステップ1502で、メソッドは、コネクタ・エントリを生成し、初期化する。ステップ1503で、メソッドは、このディスクリプタ・エントリCEListにコネクタ・エントリをリンクする。ステップ1504で、メソッドは、このディスクリプタ・エントリ用に成形されたコネクタ数をインクリメントする。ステップ1505で、メソッドは、コネクタ・エントリの接続idをセットする。ディスクリプタ・エントリの各コネクタ・エントリは、ユニークな接続idを有する。ステップ1506で、メソッドは、このディスクリプタ・エントリの接続idジェネレータをインクリメントする。接続idジェネレータは、ユニークな接続idを提供する。ステップ1507で、メソッドは、コネクタ・ディスクリプタによって指定されるユーザ・コンポーネントの生成コールバックを呼び出し、ユーザ・コンポーネントへのポインタを引数として渡し、リターンする。生成コールバックは、ユーザ・コンポーネントによって提供されるプロトコルのインタフェースへのポインタを返す。この実施例では、コネクタ・エントリは、ディスクリプタ・エントリのユニークな接続id、ユーザ・コンポーネントによって提供されるインタフェースへのポインタ、リバース・インタフェース・ポインタ、メート・コネクタ（mate connector）のモニカ（別名：moniker ）へのポインタ、出現するコンポーネントへのポインタ、および状態情報を含むフラグを備えている。状態情報は、コネクタが接続されたものか、接続中のものか、または接続解除中のものか、およびメートがスタブ（後述）であるかどうかを示す。
【０１０４】
この実施例は、「ゆるい結合（レイジー結合：lazy binding）」をリバース・インタフェースに提供する。接続がレイジー結合により確立されると、コネクタとユーザ・コネクタのリバース・インタフェース・ポインタは、リバース・インタフェースのスタブ（stub）をポイントするようにセットされ、コンポーネントに接続されたものによって提供される「実際の」リバース・インタフェースをポイントするようにはセットされない。スタブは、リバース・インタフェースの異なったインプリメンテーションである。スタブのメソッドのいずれか一つが呼び出されると、メソッドは、そのリバース・インタフェースに結合（bind）し、コネクタとユーザ・コンポーネントのリバース・インタフェース・ポインタを、結合されたリバース・インタフェースへのポインタと置き換える。続いて、各メソッドは、リバース・インタフェースの対応するメソッドを呼び出す。このようにして、リバース・インタフェースがユーザ・コンポーネントによって実際に参照されるまで、リバース・インタフェースの結合を遅らせることができる。各コネクタ・ディスクリプタは、リバース・インタフェース・スタブを生成するために、クラス・ファクトリへのポインタを含むことが好ましい。各スタブ・メソッドは、ユーザ・コンポーネントのオーサによって実現されるが、予め定められた関数を呼び出し、リバース・インタフェースへ結合する必要があるコネクタから情報を取り出す。したがって、ユーザ・コンポーネント・オーサは、コンポーネント・マネージャ構造体の内部を知る必要はない。スタブ・クラス・ファクトリが、コネクタ・ディスクリプタ内に指定されていないならば、レイジー結合は生じない。
【０１０５】
図22は、レイジー結合を示すブロック図である。コネクタ・エントリが最初に成形されると、このコネクタ・エントリは、リバース・インタフェースのスタブをポイントするようにセットされる。スタブは、リバース・インタフェースのレイジー結合を実現する。スタブのメソッドが呼び出されると、このメソッドは、コネクタのリバース・インタフェース・モニカ（後述）によって指定されるリバース・インタフェースへ結合し、その結合されたインタフェースの対応するメソッドを呼び出す。図22では、コネクタ・エントリ1601のリバース・インタフェース・ポインタ（previnterface ）は、スタブ1603をポイントする。また、ユーザ・コンポーネント1602のリバース・インタフェース・ポインタも、スタブ1603をポイントする。スタブ1603は、コネクタ・エントリ1601へのポインタを含む内部情報を有する。仮想関数テーブル1604は、各スタブ・メソッド1605をポイントする。接続が確立されると、コネクタ・エントリ1601は、リバース・インタフェース・モニカ1607をポイントするようにセットされる。ユーザ・コネクタがリバース・インタフェース・ポイントを介してメソッドにアクセスするときに、スタブ・メソッドが呼び出される。メソッド1(1605) の擬似コードで示すように、各スタブ・メソッドは、リバース・インタフェース・モニカによって識別されるリバース・インタフェースへ結合し、リバース・インタフェース・ポインタを結合されたリバース・インタフェースをポイントするようにセットし、結合されたリバース・インタフェースの対応するメソッドを呼び出し、リターンする。
【０１０６】
レイジー結合を実現するために、各コンポーネントには、コンポーネントをユニークに識別するコンポーネント・モニカ（別名）が割り当てられる。各コネクタは、コンポーネント内のコネクタをユニークに定義するコネクタ・モニカを生成する。コネクタ・モニカは、インタフェースid、インスタンス名、およびユニークな識別を提供する接続idを含んでいる。IConnectorインタフェースのメソッドGetMoniker（後述）は、コネクタのコネクタ・モニカを返す。接続が確立されると、各コネクタは、リバース・インタフェース用のコネクタ・モニカを提供される（モニカの詳細については、1993年７月６日に出願された米国特許出願第07/08/088,724 号の「オブジェクトのネーミングと結合の方法およびシステム」（“METHOD AND SYSTEM FOR NAMING AND BINDING OBJECTS”）に示されている）。リバース・インタフェース・スタブを介して結合されると、リバース・インタフェース・モニカのメソッドBindToObjectが呼び出される。
【０１０７】
この実施例において、接続（connection）は、コネクタ・ディスクリプタに持続的または非持続的に設計することができる。非持続的なコネクタは、そのコネクタへの全てのリファレンスがなくなる（例えば、リファレンス・カウントが零になる）と、そのコネクタへの割当てが解除される。一方、持続的なコネクタは、全てのリファレンスがなくなっても、割当ては解除されない。持続的コネクタが接続されると、リバース・インタフェースを識別するモニカは、そのコネクタに記憶される。リバース・インタフェース・スタブのメソッドは、このモニカを使用して、リバース・インタフェースに結合する。非持続的コネクタが接続されると、リバース・インタフェースは、そのときに結合され、リバース・インタフェース・ポインタが実際のリバース・インタフェースをポインタするようにセットされる。
【０１０８】
この発明の一実施例は、プロトコルを介して接続された全てのコンポーネントへメッセージをマルチキャスト（多重送信：multicast ）する。メッセージは、指定されたコネクタ・ディスクリプタの各接続されたコネクタのメソッドを呼び出すことによりマルチキャストされる。関数GetMulticastStubは、リバース・インタフェースのマルチキャスト・スタブのインプリメンテーションへのポイントを返す。この関数は、インタフェースidおよびインスタンス名を渡され、マルチキャスト・スタブへのポイントを返す。メッセージをマルチキャストするために、ユーザ・コンポーネントは、マルチキャスト・スタブのメソッドを呼び出す。マルチキャスト・スタブの各メソッドは、各接続されたコネクタのリバース・インタフェースの対応するメソッドを呼び出す。図23は、マルチキャスト・インタフェース・スタブの好ましいインプリメンテーションを示すブロック図である。ディスクリプタ・エントリ1701は、コネクタ・エントリ1702〜1703をポインタする。コネクタ・エントリ1702は、接続されているが、まだ結合されていない。コネクタ・エントリ1702は、そのリバース・インタフェース・ポインタとしてレイジー結合スタブ1704をポイントする。コネクタ・エントリ1703は、結合され、リバース・インタフェース1705をポイントする。マルチキャスト・スタブ1706は、ディスクリプタ・エントリ1701をポイントする。マルチキャスト・スタブ1706の各メソッドは、仮想関数テーブル1707を介してポイントされる。マルチキャスト・スタブ1708の各メソッドは、コネクタ・エントリ・リストを介してループし、コネクタ・エントリが接続されると、メソッドはリバース・インタフェースの対応するメソッドを呼び出す。メッセージのマルチキャストは、論理的には、各コネクタを列挙し、リバース・インタフェースのメソッドを呼び出すことと等価である。パラメータを返すメソッドは、この機構を介してマルチキャストすることはできない。
【０１０９】
図24は、スタブ・メソッドのサンプルを示すフローチャートである。リバース・インタフェース・スタブおよびマルチキャスト・スタブは、同じインプリメンテーションを共有する。スタブ・メソッドは、コンポーネント・マネージャによって提供される関数ConnectorStubImplementation を呼び出すためにループする。その関数が、リバース・インタフェースへのポイントを返す。スタブ・メソッドは、リバース・インタフェースの対応するメソッドを呼び出す。関数がフォールスをリターン値として返すと、スタブ・メソッドはリターンする。マルチキャストするとき、スタブ・メソッドは、リバース・インタフェース・ポインタを受信するためにループする。マルチキャストしないときには、一つだけのリバース・インタフェース・ポインタが返される。ステップ1751で、メソッドは、リバース・インタフェース・ポインタを返す関数ConnctorStubImplementationを呼び出し、値を返す。ステップ1752で、リターン値がフォールスならば、メソッドはリターンする。ステップ1753において、メソッドはリバース・インタフェースの対応するメソッドを呼び出し、ステップ1751へループする。関数ConnctorStubImplementationは、この関数がリバース・インタフェース・スタブによって呼び出されるか、スタブ内の内部情報によるマルチキャスト・スタブによって呼び出されるかを決定する。
【０１１０】
0004027679.tif 000029
【０１１１】
コード・テーブル６は、IConnectorインタフェースを示している。各コネクタ・エントリは、接続を操作するためにこのインタフェースを提供する。メソッドGetMonikerは、このコネクタ用のモニカを返す。メソッドは、コネクタ・モニカを生成し、データ・メンバをインタフェースid、インスタンス名およびこのコネクタの接続idにセットする。続いて、メソッドは、出現するコンポーネント用のコンポーネント・モニカでコネクタ・モニカを組み立て、リターンする。出現するコンポーネントは、このコネクタを成形するコンポーネントである。メソッドGetOwnerは、このコネクタの出現するコンポーネントへのポインタを返す。このコネクタが現在接続されているならば、メソッドIsConnected は値true（真）を返す。メソッドGetInfo は、インタフェース識別子、リバース・インタフェースid、インスタンス名、およびこのコネクタのステータス・フラグを集め、これらを返す。メソッドReleaseMate は、リバース・インタフェースのリリースを行うメソッドを呼び出し、リバース・インタフェース・スタブを生成する。メソッドSetMateConnectorは、このコネクタおよびユーザ・コンポーネントのリバース・インタフェース・ポインタを、渡されたインタフェースにセットする。メソッドは、このコネクタを接続されたものにセットする。メソッドGetMateConnectorがまだ結合されていないならば、メソッドGetMateConnectorはスタブに結合し、リバース・インタフェースへのポインタを返す。
【０１１２】
コンポーネント・マネージャは、接続をパシベート（passivate ）（結合解除：unbind）する機構を提供する。インタフェースまたはリバース・インタフェースの接続のいずれもパシベートすることができる。コネクタは、リバース・インタフェースをリリース（リバース・スタブでないならば）し、それをリバース・インタフェース・スタブに置き換えることによりパシベートされる。リバース・コネクタは、IConnectorインタフェースのメソッドReleaseMate を呼び出すことによりパシベートされる。接続は、IConnectorインタフェースのメソッドPassivate を呼び出すことにより、パシベートされる。このメソッドには、リバース・インタフェース・スタブが残されるべきかどうか、メート・コネクタもパシベートされるべきかどうかを示す情報が渡される。図25は、IConnectorインタフェースのメソッドPassivate のフローチャートである。ステップ1801で、渡されたフラグが、リバース・インタフェースへの接続のみをパシベートすることを示しているならば、メソッドはステップ1806に進み、そうでなければステップ1802に進む。ステップ1802で、このコネクタが、リバース・インタフェースに結合されていない、またはリバース・インタフェース・スタブに結合されているならば、メソッドはステップ1803に進み、そうでなければステップ1804に進む。ステップ1803で、メソッドは、リバース・インタフェースへ結合し、メート・コネクタのIConnectorインタフェースへのポインタを取り出す。ステップ1804で、メソッドは、メート・コネクタのIConnectorインタフェースへのポインタを取り出す。ステップ1805で、メソッドは、メート・コネクタのメソッドReleaseMate を呼び出し、メート・コネクタに、このコネクタによって提供されるインタフェースをリリースするように要求する。ステップ1806で、このコネクタが、リバース・インタフェース・スタブに結合されているならば、メソッドはステップ1807に進み、そうでなければステップ1809に進む。ステップ1807で、渡されたフラグが、リバース・スタブを残すことを示しているならば、メソッドはリターンする。ステップ1808で、メソッドは、リバース・インタフェース・スタブをリリースし、リバース・インタフェース・ポインタをNULLにセットし、リターンする。ステップ1809で、メソッドはメソッドRelease を呼び出すことにより、リバース・インタフェースをリリースする。ステップ1810で、渡されたフラグがスタブを残さないことを示すものならば、メソッドはリターンする。ステップ1811で、メソッドは、リバース・インタフェース・スタブを生成し、リバース・インタフェース・ポインタをセットして、リターンする。
【０１１３】
接続をパシベートすることの逆が、接続（connection）を結合（bind）することである。図26は、IConnectorインタフェースのメソッドBindStubのフローチャートである。ステップ1901で、このコネクタがスタブへ接続されていないならば、メソッドはエラーを返す。ステップ1902で、メソッドは、リバース・インタフェース・モニカのメソッドBindToObjectを呼び出すことにより、リバース・インタフェースに結合する。ステップ1903で、メソッドは、このコネクタを、スタブに接続されていないことを示すようにセットする。ステップ1904で、メソッドは、リバース・インタフェース・ポインタを、リバース・インタフェースへ結合されたものをポインタするようにセットする。ステップ1905および1906で、メソッドは、選択的に、メート・コネクタを接続し、そのリバース・インタフェース・ポインタをセットする。ステップ1905で、メソッドは、メート・コネクタのIConnectorインタフェースを取り出す。ステップ1906で、メソッドは、メート・コネクタのリバース・インタフェース・ポインタを、このコネクタによって提供されるインタフェースをポインタするようにセットし、リターンする。IConnectインタフェースは、リバース・インタフェースへのポインタを渡されたメソッドSetMateConnectorを提供し、そのコネクタを接続されたものとしてセットし、リバース・インタフェース・ポインタをセットする。
【０１１４】
この実施例では、コンポーネントをコンテナ・コンポーネント内に組み込むことができる。組み込まれたコンポーネントは子コンポーネント（子供）になり、コンテナ・コンポーネントは親コンポーネント（親）になる。子コンポーネントのコネクタ・ディスクリプタは、親コンポーネント上に「投射」（プロジェクト：project ）することができる。親コンポーネントのユーザには、投射されたコネクタ・ディスクリプタが、親コンポーネントのもう一つのコネクタのように見える。図27は、親コンポーネントと子コンポーネントを示すブロック図である。親は、IComponentPlug/IComponentJack プロトコル（親／子プロトコル）によってその子供に接続される。親である各コンポーネントは、IComponentPlugインタフェースおよびIComponentJackリバース・インタフェースを指定するコンポーネント・ディスクリプタを有する。したがって、コンポーネント・ディスクリプタ配列は、親コンポーネントとなることができる各コンポーネント用のIComponentPlug/IComponentJack プロトコルのエントリを含んでいる。各コンポーネントは、IComponentJackインタフェースおよびIComponentPlugリバース・インタフェースのコネクタ・ディスクリプタにより自動的に生成される。このようにして、任意のコンポーネントを、親に組み込むことができる。親／子プロトコルのディスクリプタ・エントリのCEListは、各子供のコネクタを含んでいる。図27は、親コンポーネント2010および子コンポーネント2020を示している。親2010は、コンポーネント・マネージャ2011ならびにディスクリプタ・エントリ2012および2015をもつDEListを備えている。ディスクリプタ・エントリ2012は、親／子プロトコルをサポートする。ディスクリプタ・エントリ2012のCEListは、コネクタ2013および2014を備えている。コネクタ2014は、子2020に接続されている。子2020は、コンポーネント・マネージャ2021、ならびにディスクリプタ・エントリ2022および2025を有するDEListを備えている。ディスクリプタ・エントリ2022は、親／子プロトコルをサポートする。コネクタ2024は、親2010に接続されている。ディスクリプタ・エントリ2015は、子供のディスクリプタ・エントリ2025の親への投射である。ディスクリプタ・エントリが、子供から親へ投射されると、新しいディスクリプタ・エントリが、投射であることを示す情報とともに親に追加される。子供の投射されたディスクリプタ・エントリは、投射されたことを示すようにセットされる。コネクタが、投射ディスクリプタ・エントリから成形されると、コネクタ2016は、親用に生成される。一方、破線で示すように、投射コネクタ・エントリは、IConnector、IJack またはIPlug インタフェースを提供しない。むしろ、コネクタが投射ディスクリプタ・エントリから成形されると、子供のIConnectorインタフェースがリターンされる。親は、子供が対応するコネクタ2026を成形できるように、子供のメソッドを呼び出す。子供がそれ自身親であり、成形されたコネクタが投射であるならば、子供の子供は、そのコネクタを成形するために呼び出される。親子関係は、任意のレベルのネスティングにすることができる。投射されたコネクタが成形されると、投射されたコネクタへのポインタがリターンされる。したがって、接続が子供のコネクタへ直接確立される。IComponentPlug/IComponentJack プロトコルは、一方向プロトコルである。親はIComponentPlugインタフェースのインプリメンテーションを提供しない。むしろ、任意の他の一方向プロトコルのように、IUnknownインタフェースのみが実現される。IComponentJackインタフェースは、上述したように、コンポーネント・マネージャによって提供される。
【０１１５】
関数ComponentCreateChildは、指定された親の指定されたクラスの子コンポーネントを生成し、子供を親に接続する。親コンポーネントは、フル・パス・モニカを有し、この関数は、親モニカと子供のこのモニカ（this moniker）をセットする。この実施例において、コンポーネント・マネージャは、フル・パス・モニカ、親モニカおよびこのモニカを備えている。親モニカは、子供の親を識別するモニカである。このモニカは、親の子供を識別するモニカである。コンポーネントが子供でないならば、このモニカは、コンポーネントを識別する。フル・パス・モニカは、親モニカをこのモニカに合成したものである。関数ComponentCreateChildのプロトタイプを、以下に示す。
【０１１６】
0004027679.tif 000030
【０１１７】
パラメータpComponentManager は、親コンポーネントへのポインタである。パラメータdwlClsContext およびrcidは、子供のクラスidを示す。関数は、親におって提供されるIComponentPlugインタフェースへのポインタを返す。図28および図29は、関数ComponentCreateChildのフローチャートである。ステップ2101で、親コンポーネントがフル・パス・モニカを持たないならば、メソッドはエラーを返す。ステップ2102で、メソッドは、IComponentPlugインタフェースの親コンポーネントのディスクリプタ・エントリを選択する。ステップ2103で、メソッドがディスクリプタ・エントリを選択しないならば、メソッドはエラーを返す。ステップ2104で、メソッドは、選択されたディスクリプタ・エントリからコネクタを成形する。このコネクタは、子供に接続するために使用される。ステップ2105で、メソッドは、渡されたクラスidによって指定される子供のIClassFactory インタフェースを取り出す。ステップ2106で、メソッドは、子供のインスタンスを生成し、そのIComponentインタフェースを取り出す。IComponentインタフェースのメソッドは、後述する。ステップ2107で、メソッドは、子コンポーネントを、メソッドSetParentComponentを呼び出すことにより、その親コンポーネントをポイントするようにセットする。ステップ2108で、メソッドは、子供のメソッドSetParentMonikerを呼び出すことにより、子供の親モニカをセットする。ステップ2109で、メソッドは、子供用のコンポーネント・モニカを生成する。コンポーネント・モニカは、親内の子供をユニークに識別するために、親の成形されたコネクタの接続idを含んでいる。ステップ2110で、メソッドは、子供のメソッドSetChildMoniker を呼び出すことにより、子供のこのモニカをセットする。ステップ2111で、メソッドは、生成されたコンポーネント・モニカをリリースする。ステップ2112で、メソッドは、子供のIComponentJack/IComponentPlug プロトコルのディスクリプタ・エントリから、コネクタを成形する。ステップ2113で、メソッドは、関数ComponentConnct を呼び出し、親のプラグ・コネクタを子供のジャック・コネクタに接続する。ステップ2114で、メソッドは、子供のジャック・コネクタをリリースし、リターンする。
【０１１８】
関数ComponentProjectDescriptorは、指定された子コンポーネントの指定されたインタフェースを、その親コンポーネントに投射する。関数は、親用の「投射」ディスクリプタ・エントリを生成し、それをDEListにリンクする。子供の対応するディスクリプタエントリは、それが投射されたことを示すようにセットされる。投射ディスクリプタ・エントリは、指定されたインスタンス名にセットされる。関数ComponentProjectDescriptorの好ましいプロトタイプを、次に示す。
【０１１９】
0004027679.tif 000031
【０１２０】
パラメータpComponentManager は、親コンポーネントをポイントする。パラメータpChildIComponentPlugは、親によって提供されるIComponentPlugインタフェースをポイントする。パラメータriidおよびchild-iname は、投射する子供のコネクタのインタフェースidおよびインスタンス名をそれぞれ示す。パラメータmy-name は、投射ディスクリプタ・エントリのインスタンス名を示す。パラメータcMaxConnectorsは、投射ディスクリプタ・エントリのコネクタの最大カウントを示す。図30は、関数ComponentProjectDescriptorのフローチャートである。ステップ2201で、メソッドは、子コネクタのIConnectorインタフェースを取り出す。ステップ2202で、メソッドは、インタフェースを解放する。ステップ2203で、メソッドは、渡されたインタフェースidおよびインスタンス名をもつ子供のディスクリプタ・エントリを選択する。ステップ2204で、メソッドがディスクリプタ・エントリを選択しないならば、メソッドはエラーを返す。ステップ2205で、メソッドは、渡されたインタフェースidおよび新しいインスタンス名をもつ親のディスクリプタ・エントリを選択する。ステップ2206で、メソッドがディスクリプタ・エントリを選択したならば、メソッドはエラーを返す。ステップ2207で、メソッドは、親用の投射コネクタ・エントリを生成する。ステップ2208で、メソッドは、子をもつ投射を、そのディスクリプタ・エントリが今投射されたことを子供に示すように登録する。ステップ2209で、メソッドは、投射ディスクリプタ・エントリを、親のDEListにリンクし、リターンする。
【０１２１】
コネクタは、非投射ディスクリプタエントリと類似の方法で、投射ディスクリプタエントリから成形される。しかしながら、親は、子供に、コネクタが成形されていることを通知し、子供のIConnectorインタフェースへのポインタが返される。親は、子供のIComponentインタフェースのメソッドNewProjectConnector を呼び出す。このメソッドは、子供の投射されたディスクリプタ・エントリ用のコネクタを成形する。投射されたディスクリプタ・エントリがそれ自身、投射ディスクリプタ・エントリであるならば、子供の子供が通知される。
【０１２２】
0004027679.tif 000032
【０１２３】
コード・テーブル７は、コンポーネント・マネージャによって提供されるIComponentインタフェースを定義する。IComponentインタフェースは、コンポーネントを操作するメソッドを提供する。コード・テーブル８は、コンポーネント・マネージャの内部状態情報を定義する。以下に、IComponentインタフェースのメソッドを示す。
【０１２４】
0004027679.tif 000033
【０１２５】
図31は、IComponentインタフェースのメソッドSetMonikerのフローチャートである。メソッドSetMonikerは、モニカへのポインタを渡され、このコンポーネントのフル・パス・モニカ（pmkr）を、渡されたモニカをポイントするようにセットする。ステップ2301で、このコンポーネントが子コンポーネントならば、メソッドはエラーを返し、そうでなければステップ2302に進む。ステップ2302で、このコンポーネントがすでにフル・パス・モニカを持っているならば（pmkr!=NULL）、メソッドはエラーを返し、そうでなければステップ2303に進む。ステップ2303で、メソッドは、このコンポーネントのフル・パス・モニカ（pmkr）を、渡されたモニカにセットする。ステップ2304で、メソッドは、渡されたモニカのリファレンス・カウントをインクリメントし、リターンする。
【０１２６】
図32は、クラスComponentManagerのメソッドGetMonikerのフローチャートである。メソッドGetMonikerは、このコンポーネント用のフル・パス・モニカへのポインタを返す。ステップ2401で、このコンポーネントがフル・パス・モニカを持たないならば、メソッドはエラーを返す。ステップ2402で、メソッドは、フル・パス・モニカのリファレンス・カウントをインクリメントし、リターンする。
【０１２７】
図33は、クラスComponentManagerのメソッドSetParentMonikerのフローチャートである。このメソッドは、このコンポーネントの親モニカを、渡されたモニカにセットする。コンポーネントが現在親モニカをもつならば、メソッドは現親モニカをリリースする。また、メソッドは、全ての子コンポーネントの親モニカをセットする。ステップ2501で、このコンポーネントが親モニカ（pmkParent ）をもつならば、メソッドはステップ2502で親モニカをリリースする。ステップ2503で、コンポーネントがフル・パス・モニカ（pmkr）をもつならば、メソッドは、ステップ2504でフル・パス・モニカをリリースする。ステップ2505で、メソッドは、このコンポーネントの親モニカを渡されたモニカにセットする。ステップ2506で、メソッドは、渡されたモニカのリファレンス・カウントをインクリメントする。ステップ2507で、コンポーネントが、このモニカ（pmkThis ）をもたないならば、メソッドはリターンする。ステップ2508で、メソッドは、親モニカのメソッドComposeWith を呼び出すことにより、フル・パス・モニカを、親モニカとこのモニカとを合成したものにセットする。ステップ2509で、メソッドは、メソッドRenameを呼び出し、各子コンポーネントの親モニカをセットし、リターンする。
【０１２８】
図34は、IComponentインタフェースのプライベート・メソッドRenameのフローチャートである。メソッドは、このコンポーネントの各子コンポーネントの親モニカを、渡されたモニカにセットする。また、メソッドは、コネクタの接続を解除する。ステップ2601で、メソッドは、子コンポーネントへのコネクタのDEListのディスクリプタ・エントリを選択する。ステップ2602で、ディスクリプタ・エントリが選択されると、このコンポーネントは、子コンポーネントをもち、ステップ2603に進む。そうでなければ、メソッドはステップ2606に進む。ステップ2603で、メソッドは、選択されたディスクリプタ・エントリ用の（CEListの最初のコネクタ・エントリから開始して）次のコネクタ・エントリを選択する。ステップ2604で、全コネクタ・エントリが選択されると、メソッドはステップ2606に進み、そうでなければステップ2605に進む。ステップ2605で、メソッドは、子コンポーネントのメソッドSetParentMonikerを呼び出すことにより、接続された子コンポーネントの親モニカを、選択されたコネクタ・エントリにセットする。続いて、メソッドは、ステップ2603にループし、次のコネクタ・エントリを選択する。ステップ2606〜2611で、メソッドは、コネクタの接続解除を行うためにループする。ステップ2606で、メソッドは、投射でないDEListの次のディスクリプタ・エントリを選択する。ステップ2607で、全てのディスクリプタ・エントリが選択されたならば、メソッドはリターンする。ステップ2608で、メソッドは、接続される選択されたディスクリプタ・エントリ用のCEList内の次のコネクタ・エントリを（最初のコネクタ・エントリから順に）選択する。ステップ2609で、全コネクタ・エントリが選択されたならば、メソッドはステップ2606にループして次のディスクリプタエントリを選択し、そうでなればステップ2610に進む。ステップ2610で、メソッドは、選択されたコネクタ・エントリのリバース・インタフェースをリリースし、リバース・インタフェースをNULLにセットする。ステップ2611で、メソッドは、選択されたコネクタ・エントリのリバース・インタフェース・モニカをリリースし、そのリバース・インタフェース・モニカへのポインタをNULLにセットし、ステップ2608にループし次のコネクタ・エントリを選択する。
【０１２９】
図35は、IComponentインタフェースのメソッドSetChildMoniker のフローチャートである。メソッドSetChildMoniker は、このモニカを、渡されたモニカにセットする。また、メソッドは、コンポーネントのメソッドRenameを呼び出し、その子コンポーネントをリネームする。ステップ2701で、このコンポーネントがこのモニカをもつならば、メソッドは、エラーを返し、コンポーネントは、一度セットされたそれのこのモニカのみをもつことができる。ステップ2702で、このコンポーネントがフル・パス・モニカをもつならば、このコンポーネントは、子コンポーネントではなく、メソッドはエラーを返す。ステップ2703で、コンポーネントが親モニカを持たないならば、親モニカはこの子コンポーネントが生成されたときにセットされているので、メソッドはエラーを返す。ステップ2704で、メソッドは、このコンポーネントのこのモニカ（pmkThis ）を、渡されたモニカにセットする。ステップ2705で、メソッドは、渡されたモニカのリファレンス・カウントをインクリメントする。ステップ2706で、メソッドは、親モニカのメソッドComposeWith を呼び出すことにより、コンポーネントのフル・パス・モニカを、親モニカとこのモニカとを合成したものにセットする。ステップ2707で、メソッドは、このコンポーネントのメソッドRenameを呼び出し、それの子コンポーネントをリネームし、リターンする。
【０１３０】
図36は、IComponentインタフェースのメソッドSetParentComponentのフローチャートである。メソッドSetParentComponentは、このコンポーネントの親（pParent ）を、渡されたコンポーネントをポイントするようにセットする。このメソッドは、巡回リファレンスを避けるために、親のリファレンス・カウントを増加させない。ステップ2801で、このコンポーネントが親コンポーネントをもつか、または渡されたコンポーネントがNULLならば、メソッドはエラーを返す。ステップ2802で、メソッドは、このコンポーネントの親を、渡されたコンポーネントにセットし、リターンする。
【０１３１】
図37は、IComponentインタフェースのメソッドDoEagerBindsのフローチャートである。このメソッドは、投射でない全てのコネクタ・エントリ用のスタブであって、イーガ結合（eager bind）が指定され、かつ、接続されていないスタブを結合する。ステップ2901で、メソッドは、このコンポーネントの次のディスクリプタ・エントリを（最初から順番に）選択する。ステップ2902で、全ディスクリプタ・エントリがすでに選択されているならば、メソッドはリターンし、そうでなければステップ2903に進む。ステップ2903で、選択されたディスクリプタ・エントリが投射でないならば、メソッドはステップ2904に進み、そうでなければステップ2901にループし、次のディスクリプタ・エントリを選択する。ステップ2904で、選択されたディスクリプタ・エントリがイーガ結合を示しているならば、メソッドはステップ2905に進み、そうでなければ次のディスクリプタ・エントリを選択するためにステップ2901にループする。ステップ2905で、メソッドは選択されたディスクリプタ・エントリ用の次のコネクタ・エントリを（最初から順番に）選択する。ステップ2906で、全コネクタ・エントリが既に選択されているならば、メソッドはステップ2901にループして次のディスクリプタ・エントリを選択し、そうでなければステップ2907に進む。ステップ2907で、選択されたコネクタ・エントリが接続されているならば、メソッドはステップ2905にループして次のコネクタ・エントリを選択し、そうでなければステップ2908に進む。ステップ2908で、メソッドは、選択されたコネクタ・エントリのIConnectorインタフェースのメソッドBindStubを呼出し、次のコネクタ・エントリを選択するためにステップ2905にループする。
【０１３２】
コード・テーブル2Aは、コンポーネント・ディスクリプタの定義を含んでいる。以下では、コンポーネント・ディスクリプタのフィールドが示されている。
【０１３３】
ComponentDescriptor::cConnectors
このフィールドは、コネクタ・ディスクリプタの配列のコネクタ・ディスクリプタの個数を示している。
【０１３４】
ComponentDescriptor::pConnDesc
このフィールドは、コネクタ・ディスクリプタ配列へのポインタである。
【０１３５】
ComponentDescriptor::Create
このフィールドは、コンポーネントが生成されるときに呼び出されるユーザ・コンポーネントによって提供される関数へのポインタを提供する。ユーザ・コンポーネントは、統合可能なように記述される。この関数へ渡される制御IUnknownは、コンポーネント・マネージャによって提供される。コンポーネント・マネージャは、ユーザ・コンポーネントをそれ自身に統合する。ユーザ・コンポーネントには、あるサービスを得るために使用できるコンポーネント・マネージャへのポインタが渡される。ユーザ・コンポーネントは、IPersistインタフェースのインプリメンテーションを提供する。ユーザ・コンポーネントが継続状態をもつものであるならば、ユーザ・コンポーネントはIPersistStrageインタフェースのインプリメンテーションも提供する。このようにして、コンポーネント・マネージャは、ユーザ・コンポーネントに、それ自身に継続状態になるように依頼することができる。
【０１３６】
コード・テーブル2Bは、コネクタ・ディスクリプタの記述を含んでいる。以下に、コネクタ・ディスクリプタのフィールドを示す。
【０１３７】
ConnectorDescriptor::piid
ユーザ・コンポーネントが提供するプロトコルのインタフェースidである。
【０１３８】
ConnectorDescriptor::piim
プロトコルのリバース・インタフェースidである。
【０１３９】
ConnectorDescriptor::iname
プロトコルのインスタンス名である。この名前は、ユーザ・コンポーネントによって提供される同じプロトコルの複数のインプリメンテーションを区別するために使用される。
【０１４０】
ConnectorDescriptor::flag
コンポーネントについての以下のような制御情報を示す。
【０１４１】
CNNCTR-PLUG
このフラグは、ユーザ・コンポーネントがプロトコルのプラグ・インタフェースを実現することを指定するものである。
【０１４２】
CNNCTR-JACK
このフラグは、ユーザ・コンポーネントがプロトコルのジャック・インタフェースを実現することを指定するものである。
【０１４３】
CNNCTR-REVIOPT
このフラグは、接続状態にあるリバース・インタフェースがオプションであることを示す。これは、このようなインタフェースが単に通知用または他のコンポーネントが関心のないイベントを他のコンポーネントに通知する場合に使用される。
【０１４４】
CNNCTR-EAGERBIND
このフラグは、接続が確立すると、コネクタが直ちにリバース・インタフェースへ、イーガ結合を呼ばれる結合を行うことを示す。これは、デフォルト・レイジー結合をインタフェースへ上書きする。
【０１４５】
CNNCTR-REVIPTR
このフラグは、ユーザ・コンポーネントがリバース・インタフェース・ポインタを有することを示すものである。
【０１４６】
CNNCTR-NONPERSISTENT
このフラグは、コネクタへの全てのリファレンスがなくなったときに、コネクタが継続しないことを示す。このようなコネクタは、コンポーネントがセーブされるときにセーブされる。これらのコネクタは、参照されているときにのみ存在する。このようなコネクタは、コンポーネントのクライアントによる要求により生成され、それらへのモニカが生成される。一般に、双方向のプロトコルの接続を行わない、すなわち一方向プロトコルを実現するサービス・タイプのコンポーネントが、これらを使用する。
【０１４７】
CNNCTR-PRIVATE
このフラグは、プロトコルが、コンポーネントの外部に投射されず、成形されないが、コンポーネントから子コンポーネントへ接続するために利用可能であることを示す。このようなコネクタは、コンポーネントの外部から生成されないディスクリプタ・エニュメレータまたはコネクタ・エニュメレータにはリストされないが、それらがコンポーネント内から生成されたときに見ることができる。
【０１４８】
CNNCTR-AGGREGATE
このフラグは、コンポーネント・マネージャに、このコネクタのインタフェースをコンポーネント・マネージャに統合するように指示し、コネクタのインタフェースのみがコネクタ・ディスクリプタに与えられるものであると仮定しないように指示する。piidによって指定されるインタフェースとは異なるインタフェースが要求されたときに、コンポーネント・マネージャはリバース・インタフェースのIUnknownを呼び出す。
【０１４９】
ConnectorDescriptor::cMaxConnectors
このフィールドは、コンポーネントから一度に成形できるこのコネクタのインスタンス数の初期制限を示す。コンポーネントは、実行時にこの値を調整する。調整された値は、コンポーネントの活動中継続して存在し、ここに指定された値は、新しく生成されたコンポーネントのインスタンスのデフォルト値となる。値ULONG-MAX は、成形できるインスタンス数に制限がないことを示す。
【０１５０】
ConnectorDescriptor::RevIfacePtrOff
このフィールドは、リバース・インタフェース・ポインタについての（インタフェースからの）ユーザ・コンポーネント内におけるオフセットを含む。
【０１５１】
ConnectorDescriptor::OutStubf
これらのフィールドは、特定のプロトコル用のスタブ・クラス・ファクトリへのポインタを含む。
【０１５２】
ConnectorDescriptor::Create
このフィールドは、インタフェースへのポインタを返すユーザ・コンポーネント内の関数へのポインタを含む。この関数は、コネクタが成形されたときに呼び出される。この関数は、インタフェースへのポインタを返す。
【０１５３】
ConnectorDescriptor::Delete
このフィールドは、コネクタが消去されるときに呼び出されるユーザ・コンポーネントによって提供される関数へのポインタを含む。
【０１５４】
ConnectorDescriptor::Connect
このフィールドは、接続が発生するときに呼び出されるユーザ・コンポーネントによって提供される関数へのポインタを含む。これは、ユーザ・コンポーネントに初期化を行う機会を提供する。接続のプラグ側に最初に通知され、続いてジャック側に通知される。プロトコルは、一般に、プラグ側が、その接続の通知中に、いくつかの制御コールを発行できるように設計されている。通知は、接続確立後に行われ、インタフェースは使用準備をしている。
【０１５５】
ConnectorDescriptor::Disconnect
このフィールドは、接続解除されるときに呼び出されるユーザ・コンポーネントによって提供される関数へのポインタを含む。これは、必要なクリーンアップを行う機会を提供する。プラグ側に最初に通知され、続いてジャック側に通知される。両側への接続解除通知が行われた後に、実際の接続解除が行われる。
【０１５６】
ConnectorDescriptor::Load and ConnectorDescriptor::Save
これらのフィールドは、情報をロードしセーブするために呼び出されるユーザ・コンポーネントによって提供される関数へのポインタを含む。ユーザ・コンポーネントはコンポーネントの活動中に接続に関連した状態情報をセーブする。
【０１５７】
図38は、この発明を用いたサンプル・システムを示すブロック図である。コンピュータ3001は、表示装置3002、入力装置3003および不揮発性記憶装置（補助記憶装置）3004に接続されている。コンピュータ3001は、中央処理装置3008、ビジュアル・プログラミング・マネージャ3005、利用可能コンポーネント3006および選択されたコンポーネント3007を含んでいる。ビジュアル・プログラミング・マネージャは、ビジュアル・プログラムの生成を管理する。入力装置を用いるプログラマは、リストされたコンポーネントの中からプログラムに含めるものを選択する。ビジュアル・プログラミング・マネージャは、各選択されたコンポーネントのインスタンスを生成する。コンポーネントの選択後、プログラマは、コンポーネントをどのように相互接続するかを指定する。各コンポーネントは、それがサポートするプロトコルのリストを提供する。ビジュアル・プログラミング・マネージャは、表示装置にそのリストを表示する。プログラマは、プロトコルによって接続する２つのコンポーネントを指定する。ビジュアル・プログラミング・マネージャは、指定されたコンポーネントに、プロトコル用のコネクタを成形するように指示する。続いて、ビジュアル・プログラミング・マネージャは、成形されたコネクタを接続するように指示する。
【０１５８】
図39は、ビジュアル・プログラムのサンプル表示を示す。ビジュアル・プログラムは、スクロール・バー3101および表示ボックス3102を表示する。表示ボックスは、スクロール・バーの指示の位置に対応する０から100 の数字を表示する。指示がユーザによって移動されると、表示ボックスの値は、自動的に更新される。逆に、新たな値がユーザによって表示ボックスに入力されると、これに従って指示が自動的に移動する。このようなビジュアル・プログラムを作成するために、プログラマは、スクロール・バー・コンポーネントと表示ボックス・コンポーネントを選択し、これらのコンポーネントを接続する。
【０１５９】
図40は、生成されたコンポーネントを示すブロック図である。成形されたジャック3202を有するスクロールバー・コンポーネント3201が示されている。成形されたプラグ3204を有する表示ボックス・コンポーネント3203も示されている。ジャック3202とプラグ3204は接続される。処理において、スクロールバー・コンポーネントは、スクロール・バー3101の表示に影響を与え、表示ボックス・コンポーネント3203は、表示ボックス3102の表示に影響を与える。指示が移動されると、オペレーティング・システムがスクロールバー・コンポーネントにメッセージを送る。このメッセージに応答して、スクロール・バー・コンポーネントは、その成形されたジャックを介して、メッセージをマルチキャストする。表示ボックス・コンポーネントは、メッセージを受信し、それに従ってその表示ボックスを変化させる。同様にして、ユーザが新しい値を表示ボックスに入力すると、オペレーティング・システムがメッセージを表示ボックス・コンポーネントに送信する。これに応じて、表示ボックス・コンポーネントは、プロトコルにより、接続されたジャックにメッセージをマルチキャストする。スクロール・バー・コンポーネントは、メッセージを受信し、これに従って指示を変化させる。
【０１６０】
この発明を好ましい実施例に従って説明したが、この発明がこれらの実施例に制限されるものではない。この技術分野の専門家ならば、この発明の思想の範囲内で変更を加えることができるのはいうまでもない。この発明の範囲は、特許請求の範囲によって定められる。
【図面の簡単な説明】
【図１】オブジェクトを表現するときに使用される典型的なデータ構造を示すブロック図である。
【図２】スプレッドシートのデータ構造体のサンプルを示すブロック図である。
【図３】一方向接続を示すブロック図である。
【図４】双方向接続を示すブロック図である。
【図５】プロトコルによる多重接続を示すブロック図である。
【図６】多重プロトコルをサポートするコンポーネントを示すブロック図である。
【図７】好ましいコンポーネントの構造を示すブロック図である。
【図８】コンポーネント・マネージャの好ましいデータ構造体を示すブロック図である。
【図９】実施例における２つのコンポーネント間の接続例を示すブロック図である。
【図１０】関数ComponentInit のフローチャートである。
【図１１】関数ComponentConnectのフローチャートである。
【図１２】関数ComponentDisconnect のフローチャートである。
【図１３】  IJack インタフェースのメソッドConnect のフローチャートである。
【図１４】  IJack インタフェースのメソッドNotifyDidConnectのフローチャートである。
【図１５】  IJack インタフェースのメソッドNotifyAndDisconnect のフローチャートである。
【図１６】  IJack インタフェースのメソッドDisconnectのフローチャートである。
【図１７】  IPlug インタフェースのメソッドConnectAndNotifyのフローチャートである。
【図１８】  IPlug インタフェースのメソッドNotifyWillDisconnectのフローチャートである。
【図１９】  IPlug インタフェースのメソッドDisconnectのフローチャートである。
【図２０】  IComponentJackインタフェースのメソッドNewConnectorのフローチャートである。
【図２１】  IDescriptorEntryインタフェースのメソッドExtrude のフローチャートである。
【図２２】レイジー結合を示すブロック図である。
【図２３】マルチキャスト・インタフェース・スタブの好ましいインプリメンテーションを示すブロック図である。
【図２４】スタブのサンプル・メソッドを示すフローチャートである。
【図２５】  IConnectorインタフェースのメソッドPassivate のフローチャートである。
【図２６】  IConnectorインタフェースのメソッドBindStubのフローチャートである。
【図２７】親コンポーネントと子コンポーネントを示すブロック図である。
【図２８】関数ComponentCreateChildのフローチャートである。
【図２９】関数ComponentCreateChildのフローチャートである。
【図３０】関数ComponentProjectDescriptorのフローチャートである。
【図３１】  IComponentインタフェースのメソッドSetMonikerのフローチャートである。
【図３２】クラスComponentManagerのメソッドGetMonikerのフローチャートである。
【図３３】クラスComponentManagerのメソッドSetParentMonikerのフローチャートである。
【図３４】  IComponentインタフェースのプライベート・メソッドRenameのフローチャートである。
【図３５】  IComponentインタフェースのメソッドSetChildMoniker のフローチャートである。
【図３６】  IComponentインタフェースのメソッドSetParentComponentのフローチャートである。
【図３７】  IComponentインタフェースのメソッドDoEagerBindsのフローチャートである。
【図３８】この発明を使用するサンプル・システムを示すブロック図である。
【図３９】ビジュアル・プログラムのサンプルの表示を示す。
【図４０】生成されたコンポーネントのブロック図を示す。
【符号の説明】
201 、211 コンポーネント
202 、212 、2011、2012  コンポーネント・マネージャ
203 、216 、1602  ユーザ・コンポーネント
204 コネクタ
217 コンポーネント・ディスクリプタ
215 コネクタ・ディスクリプタ
1601、1703  コネクタ・エントリ
1607  リバース・インタフェース・モニカ
1605、1708  メソッド
1701  ディスクリプタ・エントリ
1704  スタブ
1706  マルチキャスト・スタブ
1707  仮想テーブル
2010  親コンポーネント
2020  子コンポーネント
2015、2025  投射ディスクリプタ・エントリ
【図１】
0004027679.tif 000034
【図２】
0004027679.tif 000035
【図３】
0004027679.tif 000036
【図４】
0004027679.tif 000037
【図５】
0004027679.tif 000038
【図６】
0004027679.tif 000039
【図７】
0004027679.tif 000040
【図８】
0004027679.tif 000041
【図９】
0004027679.tif 000042
【図１０】
0004027679.tif 000043
【図１１】
0004027679.tif 000044
【図１２】
0004027679.tif 000045
【図１３】
0004027679.tif 000046
【図１４】
0004027679.tif 000047
【図１５】
0004027679.tif 000048
【図１６】
0004027679.tif 000049
【図１７】
0004027679.tif 000050
【図１８】
0004027679.tif 000051
【図１９】
0004027679.tif 000052
【図２０】
0004027679.tif 000053
【図２１】
0004027679.tif 000054
【図２２】
0004027679.tif 000055
【図２３】
0004027679.tif 000056
【図２４】
0004027679.tif 000057
【図２５】
0004027679.tif 000058
【図２６】
0004027679.tif 000059
【図２７】
0004027679.tif 000060
【図２８】
0004027679.tif 000061
【図２９】
0004027679.tif 000062
【図３０】
0004027679.tif 000063
【図３１】
0004027679.tif 000064
【図３２】
0004027679.tif 000065
【図３３】
0004027679.tif 000066
【図３４】
0004027679.tif 000067
【図３５】
0004027679.tif 000068
【図３６】
0004027679.tif 000069
【図３７】
0004027679.tif 000070
【図３８】
0004027679.tif 000071
【図３９】
0004027679.tif 000072
【図４０】
0004027679.tif 000073