I have written COM component in C#. Interface methods are declared in following manner:
[ComImport,
Guid("7D37EE00-143E-40DF-B177-BF091D7CD36A"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMonogramServiceHost
{
void Send(
[In, MarshalAs(UnmanagedType.BStr)] string text);
void Send([In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]byte[] data,
[In, MarshalAs(UnmanagedType.I4)] int length);
}
These methods are called from C++ code. This same interface declared in C++ is:
DECLARE_INTERFACE_(IMonogramServiceHost, IUnknown)
{
STDMETHOD(Send)(BSTR text);
STDMETHOD(Send)(uint8 *buf, int length);
};
I am calling second method. Its parameter is simply unsigned char array whose length is defined by parameter 'length'. By some unknown reason code steps into method 'void Send(string text)'. After returning from COM method debugger displays following error mes开发者_StackOverflow中文版sage:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
When I rename method to ASend correct version is called. Why is this happening? I dont see logic in this.
COM doesn't support function overloading. It isn't that clear how you are making the call, but late binding will certainly fail. IDispatch::GetIDsOfNames() is going to return the wrong dispid when asked for "Send". That's not strongly indicated in this case since you derive from IUnknown. But in itself is enough reasons to give these methods distinct names.
I'd suggest SendText vs SendBytes. Quite justified in itself, bytes and characters are not at all equivalent in Unicode.
A C# char array is a C++ uint16 array, not a uint8 array. The second signature is a mismatch.
精彩评论