消えると困るのでコピペ
コピペ元
========================================
VB.NET DLL側のプログラム
プロジェクト名は vb_dllでクラスライブラリ作成( vb_dll.dllがビルドされる )
プロジェクト → vb_dllプロパティの設定が必要です
(この設定によりビルドと同時にレジストリに登録されます)
注意:regsvr32.exe, regasm.exeを使って登録すると登録エラーか DLLとの接続に失敗してしまいました
オプション設定に問題があったのかもしれませんが原因不明です(^^;;;
プログラムソース サンプル
プログラムソース( Class1.vb )
Imports System.Runtime.InteropServices
<ClassInterface(ClassInterfaceType.None)> _
Public Class Class1
Public Function vb_function(ByRef aa As String, ByRef bb As String, ByVal xx As Long, ByRef cc As String) As Integer
Console.WriteLine("This id vb_dll.vb_function {0}", aa)
Console.WriteLine("This id vb_dll.vb_function {0}", bb)
cc = aa + bb
xx = 888
Return 0
End Function
End Class ビルドして vb_dll.dllが作成されたことを確認
同時にレジストリに登録されたことを確認 → HKEY_CLASSES_ROOT\vb_dll.Class1
DLLを呼ぶ側のプログラム
上記で作成したマネージドDLL( vb_dll.dll または cs_dll.dll )をアンマネージドプログラムで呼びます
開発言語は C++とします 処理手順は下記の通りです
1.ActiveX( COM )方式(昔のOLE)で呼び出します(レジストリから情報を取得します)
2.レジストリから取得した情報を元にしてクラス内のメソッド(メンバ、ファンクション)を呼びます
3.各パラメータをVARIANT型に変更し、逆順にセットします
4.クラスライブラリを呼びます
5.編集されたパラメータ、返り値をチェックします
6.エラー処理や獲得したメモリなどの解放
プログラムソース サンプル call_vbdll.cpp
コンパイル&リンクはコマンドプロンプトで
cl call_vbdll.cpp /link ole32.lib oleaut32.lib
プログラムソース( call_vbdll.cpp )
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <objbase.h> // COM : VB.NET のDLLと接続に必要なヘッダファイル
// ------------------------------------- BSTR <-> char変換に必要
#include <comutil.h>
#pragma comment(lib, "comsupp.lib") // 必要なライブラリ
#pragma comment(lib, "comsuppw.lib")
#define VB_DLL // VB.NETの場合
// 警告 1 warning C4996: 'strcpy' が古い形式として宣言されました。などの warning C4996を消す
#pragma warning(disable : 4996)
// -----------------------------------------------------------------
// function : main
// VB.NETで作成されたクラスライブラリ vb_dll.dllと接続し
// クラス Class1の中のメソッド vb_functionを呼ぶ
// return : 0 : success
// <> 0 : error
// -----------------------------------------------------------------
void main()
{
HRESULT h_result;
CLSID clsid;
BSTR bstr_dll;
char *strUserID = "UserIDxxx"; // ユーザーID 参照渡し
char *strPassNum = "PassNumyyy"; // パスワード 参照渡し
char strBuf[128]; // セットするメッセージなど 参照渡し
char buf[128];
int ret = 0;
BSTR bstr1 = _com_util::ConvertStringToBSTR( strUserID ); // ユーザーID
BSTR bstr2 = _com_util::ConvertStringToBSTR( strPassNum ); // パスワード
long param3 = 999; // 処理番号
BSTR bstr4 = _com_util::ConvertStringToBSTR( strBuf ); // セットされる内容
// COMをイニシャライズ(初期化)
CoInitialize( NULL );
// ProgIDからCLSIDを取得する レジストリ HKEY_CLASSES_ROOT\に登録された DLL( ActiveX )から取得
#ifdef VB_DLL
bstr_dll = _com_util::ConvertStringToBSTR( "vb_dll.Class1" );
#else
bstr_dll = _com_util::ConvertStringToBSTR( "cs_dll.Class1" );
#endif
h_result = CLSIDFromProgID( bstr_dll, &clsid );
if ( SUCCEEDED( h_result ))
{
// ------------------------------------ インスタンス作成 : TestDLL.Class1
IUnknown *pUnk = NULL;
h_result = CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnk );
if ( SUCCEEDED( h_result ))
{
// -------------------------------- インターフェイスを取得 : IDispatch
IDispatch *pDisp = NULL;
h_result = pUnk->QueryInterface( IID_IDispatch, (void**)&pDisp );
if ( SUCCEEDED( h_result ))
{
// ---------------------------- DISPIDを取得 : 呼び出したいVB側のメンバ(メソッド): vb_function
DISPID dispid = 0;
#ifdef VB_DLL
OLECHAR *func_name[] = {L"vb_function"};
#else
OLECHAR *func_name[] = {L"cs_function"};
#endif
h_result = pDisp->GetIDsOfNames( IID_NULL, func_name, 1, LOCALE_SYSTEM_DEFAULT, &dispid );
if ( SUCCEEDED( h_result ))
{
// ------------------------ vb_dllに渡すパラメータ設定
DISPPARAMS params;
::memset( ¶ms, 0, sizeof( DISPPARAMS ));
params.cNamedArgs = 0;
params.rgdispidNamedArgs = NULL;
params.cArgs = 4; // パラメータは4つ
VARIANTARG* pVarg = new VARIANTARG[params.cArgs];
// ----------------------- ★パラメータは逆順に渡ることに注意!
// 参照渡しで無い場合、VT_BYREFは必要ない
// VT_I2 : short, VT_I4 : long, VT_BSTR : BSTR
pVarg[0].vt = VT_BYREF | VT_BSTR;
pVarg[0].pbstrVal = &bstr4; // 第1パラメータには最後を4番目をセット
pVarg[1].vt = VT_BYREF | VT_I4;
pVarg[1].plVal = ¶m3;
pVarg[2].vt = VT_BYREF | VT_BSTR;
pVarg[2].pbstrVal = &bstr2;
pVarg[3].vt = VT_BYREF | VT_BSTR;
pVarg[3].pbstrVal = &bstr1;
params.rgvarg = pVarg;
// return値用
VARIANT vRet;
VariantInit( &vRet );
// ****************************************************** VB.NET DLLを COMで呼ぶ
pDisp->Invoke( dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, ¶ms, &vRet, NULL, NULL );
// ******************************************************
ret = vRet.lVal;
if ( ret == 0 ) // vb_dll, cs_dllからのリターン値をチェック
{
char *psz1;
char *psz2;
char *psz4;
psz1 = _com_util::ConvertBSTRToString((BSTR)bstr1);
psz2 = _com_util::ConvertBSTRToString((BSTR)bstr2);
psz4 = _com_util::ConvertBSTRToString((BSTR)bstr4);
char *psz;
psz = _com_util::ConvertBSTRToString((BSTR)bstr1);
printf( "pVarg->bstrVal 1 : %s\n", psz );
psz = _com_util::ConvertBSTRToString((BSTR)bstr2);
printf( "pVarg->bstrVal 2 : %s\n", psz );
printf( "pVarg->bstrVal 3 : %d\n", param3 );
psz = _com_util::ConvertBSTRToString((BSTR)bstr4);
printf( "pVarg->bstrVal 4 : %s\n", psz );
delete[] psz;
}
else
{
sprintf( buf, "VB, CS DLL からの返り値 %d\n", ret );
ret = -5;
}
delete[] pVarg;
}
else
{
ret = -4;
}
pDisp->Release();
}
else
{
ret = -3;
}
pUnk->Release();
}
else
{
ret = -2;
}
}
else
{
ret = -1;
}
// COMをクローズ
CoUninitialize();
// ------------------------ BSTRメモリを解放
SysFreeString( bstr1 );
SysFreeString( bstr2 );
SysFreeString( bstr4 );
}コマンドプロンプトで実行して確認しました
注意すべき点は、
・呼ばれるDLLがレジストリに登録されていること
・DLL名とクラス名、そしてメソッド名が一致していること
・パラメータは逆順にセットしていること
・日本語は BSTR <--> Stringで正しく変換していること
です
========================================