質問させてください。
VB.net2003にて、構造体をアンマネージDLLに渡そうとしているのですが、
マーシャリングできないというエラーが出ます。
何をしているかというと、複数のVB.netアプリで情報を共有する必要があり、
それを実現する方法として、ファイルマッピングを使用しています。
(他に.netならではの方法があるのかもしれませんが、納期が短いのと、
自分がVB6使いなもので・・・^^;)
''24バイトの構造体
<StructLayout(LayoutKind.Sequential)> Structure Person
Dim Age As Integer
<VBFixedString(20), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=20)> _
Dim Name As String
End Structure
''一人24バイト×4人で、96バイトの構造体、のつもり
<StructLayout(LayoutKind.Sequential)> Structure PersonDB
<VBFixedArray(3), MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _
Dim Persons() As Person
Public Sub Init()
ReDim Persons(3)
End Sub
End Structure
''メモリコピー関数
Declare Sub MemCopy Lib "kernel32" Alias "RtlMoveMemory" _
(ByVal hpvDestAs Integer,ByRef hpvSource As PersonDB, ByVal cbCopy As Integer)
Sub Main()
Dim DB As PersonDB
Dim Ret As Integer
Dim Pt As Integer
DB.Init()
''ここで適当にDBに対して値代入処理
Pt = マップファイルへのポインタ
''DBの内容をマップファイルに書き込み
Call MemCopy(Pt, DB ,Len(DB))
End Sub
Call部でマーシャリングできないというエラーが出ます。
構造体の中に構造体配列がない場合はうまくいきます。
某掲示板でも、構造体の中に構造体配列があるとマーシャリングが
うまくいかないという発言がありました。
やはり不可能なのでしょうか?
構造体配列をアンマネージDLLに渡す方法をご教授お願いします。
<VBFixedArray(3), MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _
の行を消してみると大丈夫かもしれないです
Y2さん
レスありがとうございます。
おっしゃられた事を試してみましたが、
「オブジェクト参照がオブジェクト インスタンスに設定されていません」
というエラーが出るようになりました。
違うっぽいです・・・
StructLayoutAttribute属性クラスのPackフィールドの値が、DLL側が要求するアライメントと一致しているか確認してみてください。
例えば、SHFILEOPSTRUCT構造体などは 1バイト単位に設定する必要があります。
それから、ハンドルをMemCopyに渡す際に、GCHandleでガベージコレクトをロックしているかどうかも確認してください。
あと、MemCopyを呼び出す必要があるのかどうかも調べた方が良いかと。
(Marshalクラスで十分な場合もありますし)
やっぱり、自力でマーシャリングするしかないんですかね?(´Д`)
Marshalクラスのメソッドを使って配列中の構造体一つ一つをマーシャリングすれば大丈夫だと思います。
↓のサンプルが参考になるかもしれないです。
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpguide/html/cpconoutarrayofstructssample.asp
MarshalAsAttributeのArraySubTypeを設定して簡単に出来たような気もしますけど...
魔界の仮面弁士さん Y2さん
レスありがとうございます。
書籍でも調べてみましたが、配列中の構造体を一つ一つ手動で
マーシャリングする必要があるみたいですね・・・
とりあえず、Y2さんのレスのサンプルと書籍を参考にして、
手動でマーシャリングしてみることにします。
ありがとうございました。