|
分類:[VB.NET/VB2005 以降]
[環境] ・Windows7(32bit) ・Visual Studio 2008 ・.NET Framework 3.5(2.0でも同様の結果でした)
お世話になります。 VB.NETからC++で作成したDLLをコールしたいのですが 構造体配列の受け渡しが意図した動作になりません。
目的 (1)VB.NETからC++DLL関数をコールし、構造体配列をVB.NETからC++へ渡す (2)VB.NETからC++DLL関数をコールし、C++で確保した構造体配列をVB.NETへ返す
(2)はうまくできたのですが、(1)が動作しません。
[C++DLL関数のインタフェース] extern "C" _declspec (dllexport) long __stdcall Input1( long cnt, LPSAFEARRY* data );
第1引数は、構造体配列の要素数です。 第2引数は、構造体配列をセーフアレイのポインタのポインタで受け取ります。
[VB.NET側のDeclare宣言] Public Declare Function Input1 Lib "xxx.dll" ( _ ByVal cnt as Integer, _ <MarshalAs(UnmanagedType.SafeArray)> _ ByRef data() as Struct1 _ ) as Boolean
[VB.NET側の構造体] <StructLayout(LayoutKind.Sequential, Pack:=4)> Public Structure Struct1 Public num as Integer <MarshalAs(UnmanagedType.BStr)> _ Public str as String End Structure
[VB.NETの処理部] Dim cnt as Integer = 2 Dim st(1) as Struct1 ' 構造体配列の要素にデータを設定 Input1(cnt, st) ←ここでE_INVALIDARG発生
[C++DLL側の構造体] typedef struct struct_Struct1{ long num; BSTR str; } Struct1;
前提として「C++DLLは変更したくない」という要件があります。 C++DLLのインタフェースを、セーフアレイのポインタのポインタではなく、 C++構造体のポインタにした場合、構造体配列をVB.NETからC++へ渡すことはできました。
このコードでVB.NETからC++DLL関数をコールすると、E_INVALIDARGが発生します。 画面上には「パラメータが間違っています。」と表示されます。 (DLL内の処理は一切動作しません。)
SafeArraySubTypeにVT_RECORD、VT_USERDEFINEDを設定してみましたが、 同様のエラーとなりました。
また、VB.NETのDeclare宣言における"MarshalAs〜"の記述を省略すると、 関数をコールするとC++DLLが動作するのですが、DLL内のSafeArrayAccessDataが うまく動作しません。(S_OKを返却するが、変なアドレスを見ている)
Declare宣言が間違っていると思い、資料を参照して 試行錯誤しているのですが(InAttribute, OutAttributeの付与など) うまく動作しません。 Declareではなく、<DllImport>での記述も試しましたが、同じ結果でした。
文字コードを明示的に指定しても同じ結果でした。
似たようなインタフェースの(2)はうまく動作しているので、 DLLの設置ミスや、構造体の定義不備ではないと考えています。
何が問題なのか、全く分かっていない状況です。 どのような記述がただしいのでしょうか。 また、記述以外(プロジェクトの設定等)にも留意点などがあるでしょうか。
ご教授のほどよろしくお願いいたします。
|