実現したいこと
あるアプリケーションをVB6ベースからC#ベースへ移行しています。
その中で、COMコンポーネントとして登録したC++ベースのDLLのメソッドを呼び出しているのですが、そのメソッドのVARIANT型の出力引数を取得したいです。
発生している問題・分からないこと
VARIANT型の出力引数を取得できていません。
VARIANT型を模倣した構造体を引数として与えていますが、出力が代入されることを期待しているプロパティがメソッドの呼び出し前後で変化していません。
該当のソースコード
C++ベースのメソッドの定義
1bool SDBServiceClass::GetField( 2 _bstr_t bstrKey, // In : key 3 _bstr_t bstrDestinationNetworkName, // In : 要求先ネットワーク名 4 _bstr_t bstrFieldName, // In : フィールド名 5 short shFieldNo, // In : フィールド番号 6 VARIANT *pvarData // Out : データ 7)
C++ベースのVARIANT型の定義
1typedef /* [wire_marshal] */ struct tagVARIANT VARIANT; 2 3struct tagVARIANT 4 { 5 union 6 { 7 struct __tagVARIANT 8 { 9 VARTYPE vt; 10 WORD wReserved1; 11 WORD wReserved2; 12 WORD wReserved3; 13 union 14 { 15 LONGLONG llVal; 16 LONG lVal; 17 BYTE bVal; 18 SHORT iVal; 19 FLOAT fltVal; 20 DOUBLE dblVal; 21 VARIANT_BOOL boolVal; 22 _VARIANT_BOOL bool; 23 SCODE scode; 24 CY cyVal; 25 DATE date; 26 BSTR bstrVal; 27 IUnknown *punkVal; 28 IDispatch *pdispVal; 29 SAFEARRAY *parray; 30 BYTE *pbVal; 31 SHORT *piVal; 32 LONG *plVal; 33 LONGLONG *pllVal; 34 FLOAT *pfltVal; 35 DOUBLE *pdblVal; 36 VARIANT_BOOL *pboolVal; 37 _VARIANT_BOOL *pbool; 38 SCODE *pscode; 39 CY *pcyVal; 40 DATE *pdate; 41 BSTR *pbstrVal; 42 IUnknown **ppunkVal; 43 IDispatch **ppdispVal; 44 SAFEARRAY **pparray; 45 VARIANT *pvarVal; 46 PVOID byref; 47 CHAR cVal; 48 USHORT uiVal; 49 ULONG ulVal; 50 ULONGLONG ullVal; 51 INT intVal; 52 UINT uintVal; 53 DECIMAL *pdecVal; 54 CHAR *pcVal; 55 USHORT *puiVal; 56 ULONG *pulVal; 57 ULONGLONG *pullVal; 58 INT *pintVal; 59 UINT *puintVal; 60 struct __tagBRECORD 61 { 62 PVOID pvRecord; 63 IRecordInfo *pRecInfo; 64 } __VARIANT_NAME_4; 65 } __VARIANT_NAME_3; 66 } __VARIANT_NAME_2; 67 DECIMAL decVal; 68 } __VARIANT_NAME_1; 69 } ;
C++ベースのメソッドの抜粋
1 case 5: // char型 // 2 // ----------- ■ 文字列(char)型の場合 3 if ( ( pvarData->vt & VT_BSTR ) && 4 ( pvarData->vt & VT_BYREF ) ) { 5 *(pvarData->pbstrVal) = bstrData.copy(); 6 } 7 break; 8 9 default: 10 m_cscSDBService.Unlock(); // ロック解除(SDBMSデータサービスクラス用) 11 return false; // 異常終了 12 13※VT_BSTR=8、VT_BYREF=16384
C#、VisualStudio上でカーソルを当てたときに表示されるポップアップから飛んだC++ベースのDLLのメソッドの定義
1bool GetField([In][MarshalAs(UnmanagedType.BStr)] string Key, [In][MarshalAs(UnmanagedType.BStr)] string NetworkName = "", [In][MarshalAs(UnmanagedType.BStr)] string FieldName = "", [In] int FieldNo = 0, [In][Out][MarshalAs(UnmanagedType.Struct)] ref object pData);
C#、現在のコードの抜粋
1var data1 = new VARIANT { vt = (ushort)(VarEnum.VT_BSTR | VarEnum.VT_BYREF) }; 2var pData1 = Marshal.AllocCoTaskMem(Marshal.SizeOf(data1)); 3Marshal.StructureToPtr(data1, pData1, true); 4var result1 = _netMSDBService.GetField(key, networkName, "TAG", 0, pData1); 5 6 [StructLayout(LayoutKind.Sequential, Pack = 8)] 7 private struct VARIANT 8 { 9 public ushort vt; 10 public IntPtr pVal; 11 }
試したこと・調べたこと
①当該メソッドを通っているかを確認しました。
別の引数によりswitch文のルートが決まります(C++メソッドの抜粋を参照)。期待している値の場合は戻り値としてtrue、期待していない値の場合は戻り値としてfalseが返るようになっており、true/falseが切り替わることは確認済みです。
現在のC#コードの場合は、case 5を通ることも問題ありません。
②デバッガでメソッドの呼び出し前後の構造体の中身を確認しました。
初期化後:pVal=0x00000000、vt=16392
メソッドの呼び出し後:pVal=0x00000000、vt=16392
pData1にも逐次適当な値が設定されています(例えば、0x0b1fd248)。
補足
VisualStudio2022、.Net8.0、C#12.0を使用しています。
C++内部の状態を確認するための仕込みをし再コンパイルしようと思いましたが、optional parameters must come after required parameters等、多くのエラーが発生している状態です。
そもそも、代入する値(bstrData(C++メソッドの抜粋を参照))が正しく設定されていない可能性も否めないのですが、現在のC#コードには問題はないのか、何か勘違いをしていないか等を知り、少しでも原因を絞りたい次第です。
何か気づいたことがあれば、ご教授いただけると助かります。些細なことでも構いません。
よろしくお願いいたします。
回答3件
あなたの回答
tips
プレビュー