1. 概要
- C++(EXE)からDLLの関数を呼び出す構成について、DLLの言語をVB6からNETFx 4.7.2 (Visual Basic) に移行する際の手順
- 必要なエラー処理等は記載されていないことがあります
2. 変更前のプログラム
- 抜粋のみ記載
- 作成したVB6のDLLは
c:\sample\Sample.dll
に配置 - C++はMFCを利用しているが、
MFCを使わない場合も同様と想定される
本例はC++側の実装に問題(VB6側と型の不一致)があり、C++のcheckDataの引数は本来CStringが望ましい。よって、MFCを使わない場合と同様とは言えない。
2.1. VB6
-
VB_Exposed = True
はAcitveXコンポーネントとして公開される事を示す値となり、Instancing プロパティに連動して勝手に変更される
CHK.cls
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "CHK"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Public Function CheckData(ByVal param1 As String) As Boolean
<処理は省略。param1に応じてTrue、またはFalseを返却する>
End Function
2.2. レジストリへの登録
- 管理者権限が必要
- 解除は必須ではないが、インタフェース変更時には必要
; 解除
regsvr32.exe c:\sample\Sample.dll /u
; 登録
regsvr32.exe c:\sample\Sample.dll
2.3. C++
- importコマンドでビルド時にActiveX DLLからの情報を組み込む
#import "C:\sample\Sample.dll"
using namespace Sample;
int checkData(int param1)
{
int iResult = 0;
//COM初期化
::CoInitialize(NULL);
// インターフェースの取得
_CHKPtr pCheck(__uuidof(CHK));
// BSTRに変換
BSTR bParam1 = param1.AllocSysString();
// 関数呼び出し
iResult = pCheck->CheckData(bParam1);
// 開放
SysFreeString(bParam1);
pCheck->Release();
// COMの終了処理
::CoUninitialize();
// 値を返却
if (iResult == 0 ) {
//false
return 0;
} else {
//true
return 1;
}
}
3. 変更後のプログラム
- 抜粋のみ記載
- 作成した.NETのDLLは
c:\sample\Sample.dll
に配置 - C++はMFCを利用しているが、
MFCを使わない場合も同様と想定される
本例はC++側の実装に問題(.NET側と型の不一致)があり、C++のcheckDataの引数は本来CStringが望ましい。よって、MFCを使わない場合と同様とは言えない。
3.1. .NET (NETFx 4.7.2)
- 検証した.NET のバージョンは、.NET Framework 4.7.2(NETFx 4.7.2)
- 公開メソッドに対するインタフェースを作成し、作成したインタフェースに属性
<ComVisible(True)>
の付加が必要 - 公開メソッドの属性の説明
- インタフェースの実装となるため、作成したインタフェースを
Implements
で指定する -
<ClassInterface(ClassInterfaceType.None)>
を追加 -
ProgId
(Visual Basic 2008 Express変換で自動付加)はC++側からの呼び出しでは使用しないが、WSHからの呼び出しでは必要
- インタフェースの実装となるため、作成したインタフェースを
- プロジェクトのプロパティで次を設定
項目 設定値 アセンブリ情報の「アセンブリをCOM参照可」 チェック ON アセンブリ情報の「ビルドタブのCOM相互運用機能」 チェック OFF
今回の例ではCI(自動ビルド)を行っているためこの設定となる。チェックをONとすると管理者権限が必要となりCIが実施できない。COM相互運用のためのアセンブリ登録(RegAsm.exe
利用)は、後述の手順で別途実施
CHK.vb
<ComVisible(True)>
Public Interface ICHK
Function CheckData(ByVal param1 As String) As Boolean
End Interface
<ClassInterface(ClassInterfaceType.None)>
<ProgId("CHK_NET.CHK")>
Public Class CHK
Implements ICHK
Public Function CheckData(ByVal param1 As String) As Boolean Implements ICHK.CheckData
<処理は省略。param1に応じてTrue、またはFalseを返却する>
End Function
End Class
3.2. レジストリへの登録
- 管理者権限が必要
- 解除は必須ではないが、インタフェース変更時には必要
-
/codebase
グローバル アセンブリ キャッシュにインストールしない場合に利用する -
/tlb
によりタイプ ライブラリ(アセンブリ内で定義されたアクセス可能な型の定義)が生成される。このファイルをC++でimport
する - 登録でアセンブリのレジストリ登録が行われ
Sample.tlb
が生成される
SET BIN=C:\Windows\Microsoft.NET\Framework\v4.0.30319
; 解除
%BIN%\RegAsm.exe /tlb c:\sample\Sample.dll /unregister
; 登録
%BIN%\RegAsm.exe c:\sample\Sample.dll /codebase /tlb
実施結果
C:\WINDOWS\system32>C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe C:\sample\sample.dll /unregister
Microsoft .NET Framework Assembly Registration Utility 4.8.4084.0
for Microsoft .NET Framework Version 4.8.4084.0
Copyright (C) Microsoft Corporation. All rights reserved.
型は正常に登録が解除されました。
C:\WINDOWS\system32>C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe c:\sample\sample.dll /codebase
Microsoft .NET Framework Assembly Registration Utility 4.8.4084.0
for Microsoft .NET Framework Version 4.8.4084.0
Copyright (C) Microsoft Corporation. All rights reserved.
RegAsm : warning RA0000 : 署名されていないアセンブリを /codebase を使用して登録すると、同じコンピューターにインストール されるその他のアプリケーションとの競合が生じる可能性があります。/codebase スイッチは署名されたアセンブリのみに使用できます。アセンブリに厳密な名前を付けて、再登録してください。
型は正常に登録されました。
3.3. C++
- importコマンドでビルド時にタイプライブラリからの情報を組み込む
- import対象がタイプライブラリ(
.tlb
)に変更
- import対象がタイプライブラリ(
- インターフェースの取得時のインタフェース名がVB6 ActiveX DLLの場合から変更となる
#import "C:\sample\Sample.tlb"
using namespace Sample;
int checkData(int param1)
{
int iResult = 0;
//COM初期化
::CoInitialize(NULL);
// インターフェースの取得
ICHKPtr pCheck(__uuidof(CHK));
// BSTRに変換
BSTR bParam1 = param1.AllocSysString();
// 関数呼び出し
iResult = pCheck->CheckData(bParam1);
// 開放
SysFreeString(bParam1);
pCheck->Release();
// COMの終了処理
::CoUninitialize();
// 値を返却
if (iResult == 0 ) {
//false
return 0;
} else {
//true
return 1;
}
}
参考情報