| ■No75321 (魔界の仮面弁士) に追記 > MarshalAs 指定は必要になるだろうということで、SafeArray 指定で > ・SafeArray > ・SafeArray, SafeArraySubType:=VT_USERDEFINED > ・SafeArray, SafeArraySubType:=VT_RECORD, SafeArrayUserDefinedSubType:=GetType(Structure1) > などを試してみましたが、HRESULT が E_INVALIDARG(0x80070057) を返すばかり。
焦って試行錯誤してるけど、理論武装無しで闇雲に試しても駄目だよなぁ…。
そもそも構造体のセーフ配列について知識が全然無いので、 VB6 当時のマーシャリングがどうなっているかを調査してみるかな。
まずは VB6 の VarType 関数を使って、バリアントの内部型を確認。
ユーザー定義型に対して VarType を使うためには、その型を パブリックオブジェクトモジュールで公開しておく必要があるので、 今回は ActiveX EXE プロジェクトにてテスト。
'=== クラス モジュール(Instacing を「1:Private」以外に設定) === Option Explicit ' No75314 のユーザー定義型 Public Type Type1 Long1 As Long Long2 As Long Long3 As Long End Type
'=== 標準モジュール === Option Explicit Public oType(0 To 9) As Type1 Private Sub Main() Debug.Print Hex(VarType(oType)) Debug.Print TypeName(oType) End Sub
結果は、VarType = &H2024、TypeName = "Type1()" 。
&H2024 は、「vbArray Or vbUserDefinedType」のことなので、 VC++ 側の表現で言えば、「VT_ARRAY | VT_RECORD」相当だと分かる。
念のため、SafeArrayGetVartype API でも調べてみる。
Declare Function SafeArrayGetVartypeVB Lib "oleaut32" Alias "SafeArrayGetVartype" _ (oType() As Any, pvt As VBA.VbVarType) As Long
Declare Function SafeArrayGetVartypeOLE Lib "oleaut32" Alias "SafeArrayGetVartype" _ (oType() As Any, pvt As olelib.VARENUM) As olelib.HRESULTS
やはり、vbUserDefinedType = VT_RECORD = &H0024 が返されてきた。
ということは、.NET 側のマーシャリングでは、 <MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VarEnum.VT_RECORD)> を指定すれば良さそうだ、ということまで理解。
でもまだうまく呼べない。次の手を考えないと。 |