消えると困るのでコピペ
コピペ元
========================================
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で正しく変換していること
です
========================================