Reputation: 19
I should pass a pointer of object array to a COM interface with the following IDL and C++ definitions: C++ code:
UpdateItem( LONG lID, LONG lNumOfFields, FieldIdEnum* pFields, VARIANT* pvValues )
IDL:
HRESULT UpdateItem( [in] LONG lID, [in] LONG lNumOfFields, [in, size_is(lNumOfFields)] FieldIdEnum* pFields, [in, size_is(lNumOfFields)] VARIANT* pvValues );
tlbimp generated C# code:
UpdateItem([In] int lID, [In] int lNumOfFields, [In] ref FieldIdEnum pFields, [In][MarshalAs(UnmanagedType.Struct)] ref object pvValues);
... and I try to call with:
FieldIdEnum[] fieldIDs = { FieldIdEnum.fi1ID, FieldIdEnum.fi2At };
object[] values = { 3, DateTime.UtcNow };
mi.UpdateItem(1, 2, ref fieldIDs[0], ref values[0]);
I get this interface from my system as result of login and authentication process... The UpdateItem method is a public member of that interface.
I want to pass two or more field and value pairs (in same time) by the two array. The field array always is passed correctly to C++ code. I have debugged C++ code and the "FieldIdEnum* pFields" represents the first element of an integer array and the 2nd element (pFields1) is correct too. The pField[] is a c-style array.
But the 2nd array is a variant array with various element type in this case an integer and a date time. This appears as a SafeArray at c++ side instead of c_style array. I have checked this 2nd array too, it is a simple variant array if the method calling starts from another C code, but C# tries to marshal it to safearray.
I have changed the C# definition to
UpdateItem([In] int lID, [In] int lNumOfFields, [In] ref FieldIdEnum pFields, [In] ref object pvValues);
It does not work I always get an exception like "Value does not fall within the expected range." "System.Exception {System.ArgumentException}"
I have tried to use/marshal various managed/unmanaged types and Intptr, did not work.
I have found an other topic with same/similar problem, I could not make it work.
How should I pass a pointer of object array to COM interface?
Upvotes: 2
Views: 271
Reputation: 19
I have found the solution. I have redefined the interface method:
void UpdateItem([In] int lID, [In] int lNumOfFields, [In] ref FieldIdEnum pFields, [In][MarshalAs(UnmanagedType.LPArray)] object[] pvValues);
... and call this as:
FieldIdEnum[] updateFieldIDs = { FieldIdEnum.fi1ID, FieldIdEnum.fi2At };
object[] values = { 3, DateTime.UtcNow };
mi.UpdateItem(id, updateFieldIDs.Length, ref updateFieldIDs[0], values);
Thank you for guidance.
Upvotes: -1