独自インターフェースと通信
すでに説明したように、COMサーバとCOMクライアントが別のプロセスで動いている場合はproxyとstubが動作しています。
EXEサーバの説明で用いたサンプルコードでは、
IClassFactoryやISequentialStreamといったシステム定義のインターフェースを用いてきました。
COMシステムはこれらのインターフェースに対するproxyやstubを持っているため、
COMサーバがDLLであってもEXEであっても同じように動作します。
しかし、COMシステムは独自インターフェースの内容を知りません。
したがって、独自インターフェースを定義する際には、
proxyやstubを提供する方法を考えておく必要があります。
MIDLには、タイプライブラリを生成する機能と、proxyとstubのソースコードを生成する機能が備わっています。
デュアルインターフェースの場合は、タイプライブラリをCOMシステムに登録することで、
タイプライブラリの内容に基づくproxyとstubをCOMシステムが自動的に生成してくれるようになります。
タイプライブラリは、32bitのインターフェースと64bitのインターフェースを区別していません。
タイプライブラリをCOMシステムに登録しておけば、32bit OSからでも64bit OSからでも独自インターフェースを呼び出せるようになります。
MIDLで生成されたソースコードを利用すると、proxyとstubを準備することも可能です。
あるいは、独自にproxyとstubを実装することも可能です。
これらの方法を用いる場合は、32bit OSと64bit OSのそれぞれに対しproxyとstubを用意する必要があります。
こちらの方法はタイプライブラリと比べ複雑になりますので、
可能な限りタイプライブラリを用いると良いでしょう。
タイプライブラリを用いたproxyとstubの利用
タイプライブラリに保存されたインターフェースがオートメーション互換である場合、
タイプライブラリが登録されるときに、そのproxyとstubもCOMシステムが登録してくれます。
オートメーション互換のインターフェースとは、
引数がVARIANTで表現可能で、戻り値がHRESULTであるインターフェースのことです。
デュアルインターフェースであればオートメーション互換になります。
いいかえれば、次の手順を踏めば、
独自インターフェースを備えたCOMサーバを、proxyとstubを介して呼び出せるようになります。
.idlでdual指定したinterfaceを作成する。
生成されたタイプライブラリをCOMシステムに登録する。
coclassでそのinterfaceを使用する。
デュアルインターフェースのEXEサーバとして実装された
サンプルCOMサーバは、
独自インターフェースIIchigo4を備えたcoclassで、
そのCLSIDはCLSID_Ichigo4、ProgIDはIchigo4.Logwriterです。
EXEサーバは別のプロセスとして起動されますが、
タイプライブラリを利用してシステムが提供するproxyとstubのおかげで、
C++言語からでも、Javascriptなどのスクリプト言語からでも、
proxyとstubを介してこのcoclassを呼び出すことができます。
C++言語から呼び出すコードは次の通りです。
//
// Copyright (c) 2016 The Ichigopack Project (http://ichigopack.net/).
//
#include <windows.h>
#include <ole2.h>
#include <iostream>
#include <string>
#include <iomanip>
#include "ichigocom4_if.h"
// {287AF1C7-7618-4C81-952C-B70238A474CB}
static const GUID CLSID_Ichigo4 =
{ 0x287af1c7, 0x7618, 0x4c81, { 0x95, 0x2c, 0xb7, 0x2, 0x38, 0xa4, 0x74, 0xcb } };
int main(int argc, char** argv)
{
HRESULT hr;
hr = CoInitialize(NULL);
if ( FAILED(hr) ) {
std::cout << "CoInitialize() error: " << hr << std::endl;
return 1;
}
IIchigo4* pObj = NULL;
hr = CoCreateInstance(
CLSID_Ichigo4, NULL,
CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER |
CLSCTX_LOCAL_SERVER,
IID_IIchigo4, (LPVOID*)&pObj);
if ( SUCCEEDED(hr) ) {
BSTR bstr = SysAllocString(L"ichigopack COM sample 4 (exe)\n");
if ( bstr != NULL ) {
pObj->Write( bstr );
SysFreeString( bstr );
} else {
std::cout << "SysAllocString() error" << std::endl;
}
pObj->Release();
} else {
std::cout << "CoCreateInstance() error: "
<< std::hex << std::setfill('0')
<< std::setw(8) << hr << std::endl;
}
CoUninitialize();
return 0;
}
Javascript言語から呼び出すコードは次の通りです。
COMサーバを呼び出すJavascriptは、.wsfの拡張子を持つWindows Scriptファイルとして保存する必要があります。
<job id="ichigocom4">
<script language="JScript">
var obj = new ActiveXObject("Ichigo4.Logwriter")
obj.Write("ichigopack COM sample 4 (javascript)\n");
</script>
</job>
関連ページ
COM/ActiveXの解説ページ 目次
前の項目: タイプライブラリの登録とその利用