3

ほぼ 1 週間、次の問題に直面しています。COM アプリケーションに送信する必要がある C# 構造体の配列があります。しかし、COMメソッドを呼び出すと、次のようになります

エラー: System.Runtime.InteropServices.MarshalDirectiveException' が発生しました

追加情報: 'パラメーター #5' をマーシャリングできません: マネージド型とアンマネージド型の組み合わせが無効です (Int/UInt は SysInt または SysUInt とペアにする必要があります)。

IDL ファイルは、C# インターフェイスで拡張/派生されています。

IDL で定義されているメソッドは次のとおりです。

[helpstring("Method MyCallbackMehtod")]
    HRESULT MyRequestFinished(
        [in] long    callId,
        [in] unsigned int nrElemArray1,
        [in, size_is(nrElemArray1)] MyStruct ElemArray1[],
        [in] unsigned int nrElemArray2,
        [in, size_is(nrElemArray2)] MyStruct ElemArray2[]
);

C# インターフェイス:

 [ComImport, Guid("xxxxxxxx-xxxx-xxxx-xxx-xxxxxxxxxx")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IMyInterface
    {

        void MyRequestFinished(
            [In] 
            long callId,

            [In] 
            uint nrElemArray1,

            [In,MarshalAs(UnmanagedType.LPArray,SizeParamIndex=1)] 
            IntPtr ElemArray1,

            [In]
            uint nrElemArray2,

            [In, MarshalAs(UnmanagedType.LPArray,SizeParamIndex = 3)]  
            IntPtr ElemArray2);
}

MyStruct の定義は次のとおりです。

[StructLayout(LayoutKind.Sequential,Pack=1)]
    public struct MyStruct
    {
        public double setValue;
        public double actualValue;
        [MarshalAs(UnmanagedType.I4)]
        public MyEnum myResult;
    }

    [ComVisible(true)]
    public enum MyEnum 
    {
        Val1,

        Val2,

        Val3
    }

COM メソッドへの呼び出しが呼び出されるコード スニペット:

IntPtr pMyElemArray1  = IntPtr.Zero;
IntPtr pMyElemArray2 = IntPtr.Zero;

MyStruct[] MyElemArray1= GetArray1();
MyStruct[] MyElemArray2= GetArray2();

int lengthElemArray1= MyElemArray1.Length;
int lengthElemArray2= MyElemArray2.Length;

pMyElemArray1 = Marshal.AllocCoTaskMem(Marshal.SizeOf(MyElemArray1[0]) * lengthElemArray1);
pMyElem2 = Marshal.AllocCoTaskMem(Marshal.SizeOf(MyElemArray2[0]) * lengthElemArray2);

int rundef = (int)pMyElemArray1 ;
for (int i = 0; i < lengthElemArray1; i++)
{
     Marshal.StructureToPtr(MyElemArray1 [i], (IntPtr)rundef, false);
     rundef += Marshal.SizeOf(MyElemArray1[i]);
}

rundef = (int)pMyElemArray2;
for (int i = 0; i < lengthElemArray2; i++)
{
    Marshal.StructureToPtr(MyElemArray2[i], (IntPtr)rundef, false);
    rundef += Marshal.SizeOf(MyElemArray2[i]);
}

// Notify COM component
//here i get the error
  myComObject.MyRequestFinished(callId,
                       ((uint)lengthElemArray1),
                       pMyElemArray1,
                       ((uint)lengthElemArray2),
                       pMyElemArray2);
//....
}
4

1 に答える 1

0

LPArraytype のパラメータには適用できませんIntPtr。パラメータ タイプを配列に変更するか、MarshalAs属性を削除してみてください。

void MyRequestFinished(
    [In]
    long callId,

    [In]
    uint nrElemArray1,

    [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
    MyStruct[] ElemArray1,

    [In]
    uint nrElemArray2,

    [In]  
    IntPtr ElemArray2);
}

個人的には、IntPtr ではなく配列を渡す方が呼び出し側のロジックがはるかに単純になるため、私は配列を渡すことを好みます。

于 2014-02-16T11:14:18.660 に答える