[C++]ATLで64bit版のCOMを作成する

Twitter / Marupeke_IKD: Windows7下でVisualStudio2005 …
https://twitter.com/Marupeke_IKD/status/245237326995927040

なところで、「Windows7下でVisualStudio2005で64bitなATLをVC++で作って、それを同じくVS2005環境で64bitビルドなVBで使おうとして「参照の追加」をするのだけど」の部分が気になって、一応確認してみたという話を少し。

VB6 自体は、Windows 7 上では動かないので、

  • Windows 7 上の Visual Studio 2005 で 64bit の COM を作成
  • Windows XP(かな?)の VB6 で先の COM を参照

なところでしょう。「VB の参照設定に出てこない」というところは、ファイルを参照させれば良いような気もするのですが、ちょっと実験してみます。

■環境

同じ環境を用意したい…つーのは面倒なので、似た環境を用意します。

  • Windows 7 x64 の Visual Studio 2010 で COM を作る。
  • Windows 7 x64 の Excel x86 を使って試す。

VB6 から参照するのも、Excel VBA から参照するのも似たようなものなので、これでテストします。以前、よくやっていた方法です。

■ATLでCOMを作る

  1. Visual Studio 2010 で「ATLプロジェクト」を選択

  1. プロジェクトに「ATLシンプル オブジェクト」を追加

  1. インターフェースを「デュアル」にするのを忘れずに

  1. クラスビューを使って、適当にメソッドやプロパティを追加(ここでは ICSmpのほうに追加)

IDL ファイルが自動生成されます。

 [
 	object,
 	uuid(A64C2AE7-E5C9-4B95-9C69-B48CB5E97966),
 	dual,
 	nonextensible,
 	pointer_default(unique)
 ]
 interface ICSmp : IDispatch{
 	[propget, id(1)] HRESULT Length([out, retval] SHORT* pVal);
 	[propput, id(1)] HRESULT Length([in] SHORT newVal);
 };
 [
 	uuid(9394A921-EE32-4302-B544-90EC6D538D69),
 	version(1.0),
 ]
 library SampleAtlCom64Lib
 {
 	importlib("stdole2.tlb");
 	[
 		uuid(C8A6D4E6-BFAF-48B4-AE57-F65847F2ACA6)		
 	]
 	coclass CSmp
 	{
 		[default] interface ICSmp;
 	};
 };
  1. プロパティのコードを修正
// CCSmp
STDMETHODIMP CCSmp::get_Length(SHORT* pVal)
{
	*pVal = m_length;
	return S_OK;
}


STDMETHODIMP CCSmp::put_Length(SHORT newVal)
{
	m_length = newVal;
	return S_OK;
}

ひとまず、これをビルドすると「Win32」のほうの 32bit 版の COM が作成できます。

■64bit版のCOMを作る

構成マネージャを使って「新規作成」をします。すると、Win32 の構成をコピーして「x64」の構成ができます。

VC++のライブラリは自動的にx64のほうに切り替えられます(これは、VS2005の頃は手動だったはず)。

これをビルドすると、x64/Debug というフォルダに COM が作成されます。Win32 のほうは、Debug フォルダですね。

■Excel VBA から 64bit COM を参照する

Excel VBA を立ち上げて、「ツール」→「参照設定」を開きます。

参照ボタンを押して、先の x64/Debug にある COM(*.dll)を参照させます。

無事に参照が出来た模様

オブジェクトブラウザでも確認

さっき適当に作った Length というプロパティが見れます。

■Excel VBA で動作確認する。

テストコードを使ってステップ実行してみる。

まぁ、普通に実行ができるわけです。

一応 Excel 2010 を確認しておくと、「ファイル」→「ヘルプ」から 32ビット版なのか 64ビット版なのかが分かります。

■どうして、Marupeke_IKD さんの環境では動かないのか?

という訳で、手元の環境では ATL で x64 の COM を作って 32ビット版の Excel VBA から利用できたわけです。
ただし、VB6 の 64ビット環境については、

Visual Basic 6.0 で 64 ビットの Windows オペレーティング システムの使用方法について
http://support.microsoft.com/kb/894373/ja

に書いてある通り、微妙な動きをするそうなので Win32 に揃えてしまったほうがよさそうですね。
あと、Excel 2010 のヘルプを開いて「64」で検索して、「Microsoft Office の 32 ビット版と 64 ビット版を選択する」の項目を見ると、いまいち Office 64bit の下位互換性が不完全であることが分かります。まぁ、不完全というか「切り捨てた」と言っていいのでしょうが、インストールしている office が 32ビットなのか64ビットなのかを判別しながら、Excel VBA を組むのはやりたくないですよね。という訳で、特に不具合がなければ32ビット版にするのがよいのかも。

このテストで作ったのはシンプルな「ATLシンプル オブジェクト」なので、MFC やら外部 DLL を使っている場合は、もっと注意が必要ですよね。そのあたりでうまく参照設定できないのかもしれません。

カテゴリー: C++ パーマリンク