I want to call a method in a COM component from C # using COM interaction. These are the signature of the methods:
long GetPrecursorInfoFromScanNum(long nScanNumber, LPVARIANT pvarPrecursorInfos, LPLONG pnArraySize)
and this is an example code (which I checked really works) to call it in C ++:
struct PrecursorInfo { double dIsolationMass; double dMonoIsoMass; long nChargeState; long nScanNumber; }; void CTestOCXDlg::OnOpenParentScansOcx() { VARIANT vPrecursorInfos; VariantInit(&vPrecursorInfos); long nPrecursorInfos = 0; m_Rawfile.GetPrecursorInfoFromScanNum(m_nScanNumber, &vPrecursorInfos, &nPrecursorInfos);
And here is the corresponding C # signature after importing the typelib COM component:
void GetPrecursorInfoFromScanNum(int nScanNumber, ref object pvarPrecursorInfos, ref int pnArraySize);
If I'm not mistaken, I need to pass a null value to pvarPrecursorInfos to make COM interoperability a marshal as the expected VT_EMPTY option. When I do this, I get a SafeArrayTypeMismatchException - not surprisingly, looking at how the result is expected to be processed in the sample. So I tried to use my own marshaler. Since a cannot change the component itself, I tried to present it as follows:
[Guid("06F53853-E43C-4F30-9E5F-D1B3668F0C3C")] [TypeLibType(4160)] [ComImport] public interface IInterfaceNew : IInterfaceOrig { [DispId(130)] int GetPrecursorInfoFromScanNum(int nScanNumber, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MyMarshaler))] ref object pvarPrecursorInfos, ref int pnArraySize); }
The TypeLibType and DispID attributes are the same as in the original version. This works until the MyMarshaller.GetInstance () method is called, but I don't get the callback in MyMarshaller.NativeToManaged. Instead, an access violation is reported. So is this a reliable approach? If so, how can I make it work? If not: are there any alternatives?
(Just a footnote: theoretically, I could try using managed C ++ to invoke the component initially. However, there are many other methods that work well with COM interoperability, so I would really like to stick with C # if there is any way. )