0
0

[初級] COMの基本的な仕組み(超ざっくり)

Posted at

COMの基本的な仕組み(超ざっくり)

本記事の前提条件は以下の通りです。

  • 初心者向け
  • とは言っても、それなりにWindowsでCOMを使うということがどういうことわかっている人向け
  • あくまでもプログラマー向け
  • 利用する言語は特に想定していない
  • ざっくり概要しか説明しないので細かいことは気にしないでいただきたい
  • 本記事は上から順番に読む前提となっている

そもそもどういうものか

とりあえずは、DLL (Dynamic Link Library) を、特別な仕様に基づいてすごく拡張したもの、と考えてよいと思う。
ただし、COM オブジェクトはあくまでも「オブジェクト」であり、つまり状態を持つ、ということに注意が必要ではある。

とはいっても、DLL がグローバルのデータを持てるということと、別に COM オブジェクトに状態を持たせる必要はない、ということを考えると、結局大した違いはないとも言える。

なお、ここで言っている「状態」は、COM 特有の参照カウントを用いたライフサイクル管理の話ではなく、ADO の場合の DB への接続であったり、EXCEL の場合のシートのデータであったり、オブジェクトがデータを保持しており、それを操作することが多い、という話なのであしあからず。

COM サーバーとクライアント

ようするに、あるオブジェクトの実装およびそのオブジェクトを生成するためのファクトリ・メソッドを持った実行可能モジュールを COM サーバーといい、作成されたインスタンスが COM オブジェクトであり、それを利用するコードを COM クライアントと言う、ということである。

COM サーバーにはインプロセスサーバーとアウトプロセスサーバーがある。
インプロセスサーバーはDLLであり、例えば VBA で ADO を使う場合はこんな風にするが、これは(これも例えばであるが)msado15.dll などを COM サーバーとして呼び出すことになる。

vb
Set ado = CreateObject("ADODB.Connection")

これに対して、例えば Excel はアウトプロセスサーバーであり、下記のようにすると、インストールされた EXCEL.EXE が呼び出される。

vb
Set excel = CreateObject("Excel.Appplication")

アウトプロセスサーバーにすると、例えば 32bit の COM サーバーを 64bit の COM クライアントから呼び出すことができるので、いざという時に微妙に便利だったりする。

COM オブジェクトの生成

どのような言語でもたいてい、CreateObject とか CreateInstance のような関数で COM オブジェクトを作成することになるが、この時、目的とする COM コンポーネントの ProgID か CLSID を引数で指定することになる。

ProgID と CLSID

ProgID は、例えば、ADODB.Connection のような文字列である。
CLSID は、GUID であり、例えば {00000514-0000-0010-8000-00AA006D2EA4} のようなものとなる。

レジストリから COM サーバーモジュールのパスを取得する

  • ProgID が指定された場合、COM システムはレジストリのHKEY_CLASSES_ROOT から ProgID を探す。見つかったキーのサブキー CLSID から CLSID を取得する
  • CLSID が指定された場合、あるいは ProgID から CLSID が取得できた場合は、レジストリの HKEY_CLASSES_ROOT\CLSID から CLSID を探す
  • 見つかったキーのサブキー InprocServer32 に該当 DLL へのパスが書いてあるので、この DLL をロードする(アウトプロセスサーバーの場合は LocalServer32 にある EXE へのパス)

いうまでもなく、レジストリのキー群は regsvr32.exe によって書き込まれたものである。
※厳密に言うと regsvr32.exe はCOM サーバーに実装されているはずのレジストリ登録用関数を呼び出すだけなので、実質的には COM コンポーネント自体が書き込んでいるのだが。

64bit Windows での 32bit アプリケーションの場合や DCOM の場合は、レジストリの設定方法も異なるので留意。

COM オブジェクトの生成

COM システムは、DLL あるいは EXE をロードし、COM の仕様に従って COM コンポーネントのインスタンス(=COMオブジェクト)を生成し、呼び出し元に返却する。

以上。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0