C#のVARIANTパラメータ型を使用したマネージAPIメソッドの呼び出し

私は私のC#アプリケーションで使用しようとするActiveX DLLがあります。ほとんどのinteropメソッドは機能します。私は次のメソッド(アンマネージド定義)に問題があります。

HRESULT SendData([in] long lChID, [in] short nIndex, 
    [in] VARIANT vData, [out, retval] VARIANT_BOOL *bResult);

VARIANT のデータ型は私には珍しいもので、COMとして何をすべきか分かりませんし、マーシャリングは新しいトピックです。

BOOL CControl::SendData(long lChID, short nIndex, const VARIANT& vData)
{
    BOOL result;
    static BYTE parms[] = VTS_I4 VTS_I2 VTS_VARIANT;

    InvokeHelper(0x1f, DISPATCH_METHOD, VT_BOOL,
        (void*)&result, parms, lChID, nIndex, &vData);

    return result;
}

.NETツール AxImp.exe を使用して、メソッドのマネージラッパーを取得しました。

[DispId(31)]
[MethodImpl(MethodImplOptions.InternalCall,
    MethodCodeType = MethodCodeType.Runtime)]
public virtual bool SendData([In] int lChID, [In] short nIndex, 
    [MarshalAs(UnmanagedType.Struct), In] object vData);

C#メソッドラッパーは正しく生成されていますか?

vDataパラメータを初期化して設定する正しい方法は何ですか?

編集:

3番目のパラメータVARIANTを解読するためのコード例

VARIANT var;
VariantInit(&var);

var.vt = VT_UI1 | VT_BYREF;
var.pbVal = (unsigned char *)pSend;

if (!m_Control.SendData(m_lCurChID, m_combo.GetCurSel() + 1, var))
    AfxMessageBox(_T("SendData failed"));

var.vt var.pbVal は私には分かりません。対応するコードはC#にありますか?

1
コメントありがとうございます。私はC ++ VARIANTがC#で一対一の定義を持っていないことを学びました。私は質問にサンプルコードを追加しました。それに対応するC#コードを書くための貴重な情報がすべてありますか?ありがとう
追加された 著者 J Pollack,
どのような種類のデータ型が渡されるべきかわからない場合は、そのデータ型を取得することはできません。これを使用するサンプルコードをもっと探してみるか、ベンダーや著者から助けを求めてください。
追加された 著者 Hans Passant,
C#にVariant型がないので型がわからない場合は、このオブジェクトのようなものを試すことができます。xyz = MyThirdPartyLib.MyThirdPartyLibFunction();タイプt = typeof(xyz);バリアントを参照するために使用する型を決定する。MyThirdPartyLib.MyThirdPartyLibFunctionをメソッド/関数で置き換える。
追加された 著者 MethodMan,

1 答え

System.Runtime.InteropServices .Marshal.GetNativeVariantForObject()メソッドを使用します。 vDataの実際の内容を知っていると仮定すると、IntPtrでinteropのシグネチャを定義し、そのメソッドの結果をinPtrに渡すことができます。

したがって、署名は次のようになります。

public virtual bool SendData(
    [In] int lChID, 
    [In] short nIndex, 
    [MarshalAs(UnmanagedType.Struct), In] IntPtr vData);

呼び出しコードは次のようになります。

MyClass vData = ...;// build the actual data. 
IntPtr variantPtr = Marshal.AllocHGlobal(Marshal.SizeOf(vData ) + ???);//Allocate the space. I'm not entirely sure how much space you need here in addition to the base object size.
Marshal.GetNativeVariantForObject(vData , variantPtr); //fills the allocated memory with the VARIANT.

それを今上に行くと、疑問があるようです。これは、多くの場合、デフォルトのマーシャラーに任務を遂行させるための最良のコースです。あなたのvDataがbyte []の場合、単純にinterop関数をbyte []で定義し、何が起こるかを見てください。

1
追加された
私はバイト配列を渡す場合、それはちょうど動作する必要がありますか?マーシャリングに関する知識はほとんど、または実際には分かっていないので、IntPtrでinteropシグネチャを定義する方法の例を挙げることはできますか?
追加された 著者 J Pollack,
私はいくつかの提案されたコード例で私の答えを編集しました。
追加された 著者 Avner Shahar-Kashtan,