15
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

COM(Component Object Model)についてふわっと学習していく その2 本当に言語非依存なのか?

Last updated at Posted at 2017-06-03

#前回
その1 導入編 
導入編ということで、とりあえず理屈は置いておいてCOMを使ってみる、
ということを行いました。

今回は、COMが「特定の言語に依存しない」という点に着目して、
いろんな言語でCOMを呼び出してみたいと思います。

やることは前回と同じ、IEの起動です。

PHP

ComTest.php
<?php
	$ie = new COM("InternetExplorer.Application");
	$ie->Visible = true;
?>

これだけです。
呼び出し方はVBSとほぼ同じですね。

PHPではCOMクラスが予め用意されているので、追加のパッケージ等は必要ありません。
http://php.net/manual/ja/class.com.php

Python

ComTest.py
import win32com.client
ie = win32com.client.Dispatch("InternetExplorer.Application")
ie.Visible = True

こちらもほぼ同じです。
しかし、COM呼び出し機能はデフォルトでは入っていないので、追加でインストールする必要があります。
https://sourceforge.net/projects/pywin32/

C#

Program.cs
using SHDocVw;
namespace ComTestByCSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            InternetExplorer ie = new InternetExplorer();
            ie.Visible = true;
        }
    }
}

SHDDocVw名前空間のクラス、インターフェースを使用するために
参照に「Microsoft Internet Controls」を追加する必要があります。

参照マネージャ=>COM=>タイプライブラリから追加できます。

タイプライブラリについて、マイクロソフトのドキュメントでそれらしいものが
見つけられなかったのですが、いろいろなところをググッた結果、
要するにCOMのインターフェース定義が書かれているファイルのことのようです。

これを用いることで、COMで公開されているインターフェースを
呼び出し側の「型」として使用できるようになるわけですね。

VBS, PHP, Pythonの実装例では文字列からオブジェクトを生成しているので、
このあたりの仕組みが異なるようです。

VB.NET

Module1.vb
Imports SHDocVw
Module Module1
    Sub Main()
        Dim ie As InternetExplorer = New InternetExplorer
        ie.Visible = True
    End Sub
End Module

C#の兄弟言語、VB.NETでも実装方法は変わりません。

C++

ComTest.cpp
#include "stdafx.h"
#include <atlbase.h>
#include <exdisp.h>
#import "C:\WINDOWS\system32\shdocvw.dll"
int _tmain(int argc, _TCHAR* argv[])
{
	CoInitialize(NULL);
	{
		IWebBrowser2Ptr ie;
		CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (VOID**)&ie);
		ie->put_Visible(VARIANT_TRUE);
	}
	CoUninitialize();
	return 0;
}

#importディレクティブを使用してタイプライブラリを読み込んでいます。
https://msdn.microsoft.com/ja-jp/library/8etzzkb6.aspx

これにより、C#やVB.NETと同様、固有のクラスやインターフェースが使えるようになるわけですね。
しかし、C#やVB.NETと比べるとコードがやや複雑です。

まず、COMを利用する前にCOMの初期化、利用後におよび初期化解除が必要です。
(CoInitialize(), CoUninitialize())

IWebBrowser2PtrはIWebBrowserインターフェースのスマートポインタです。
IWebBrowserを直接使用するのではなく、スマートポインタを使うようです。
(使わなくてもできるようですが、未調査)

また、CoUninitialize()はCOMのオブジェクトが未開放の状態で実行するとエラーになるので、
ローカルスコープを一段掘ることで、
CoUninitialize()呼び出しの前にIWebBrowser2Ptrが解放されるようにしています。

CoCreateInstance()で実際のオブジェクトを生成するわけですが、引数が多いです。
https://msdn.microsoft.com/ja-jp/library/windows/desktop/ms686615(v=vs.85).aspx

rclsid => クラスのID
pUnkOuter => とりあえずNULLで問題ないようです(未調査)
dwClsContext => とりあえずCLSCTX_LOCAL_SERVERで問題ないようです(未調査)
riid => インターフェースのID
*ppv => 生成されるオブジェクト
(戻り値はHRESULT型になっているので、オブジェクトは参照渡しで取ってくるようになっているようです)

第二、第三引数についてはよくわかっていませんが、
今後余裕があったらちゃんと調査するかもしれません。

よくわかっていないところが多くなってきましたね。
C++で特にわからないところが多いのは、よりCOMっぽい実装になっているからかと推測しています。
(他の言語ではうまくラップしているので見えていない部分をきちんと実装しないといけない)

今回の目的は「とりあえず使えること」ですので、難しいところは一旦スルーします。

まとめ

実装方法にいくつかのパターンがありましたが、
様々な言語で実装できることを確認できました。

次回

その3 COMコンポーネント実装 
次回は、これまで「呼ぶ側」に着目していましたが、
いよいよ「呼ばれる側」を作ってみたいと思います。

15
14
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
15
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?