c – COM interop:如何使用ICustomMarshaler调用第三方组件
发布时间:2020-12-16 07:28:39 所属栏目:百科 来源:网络整理
导读:我想使用COM互操作从C#调用COM组件中的方法.这是方法签名: long GetPrecursorInfoFromScanNum(long nScanNumber,LPVARIANT pvarPrecursorInfos,LPLONG pnArraySize) 这是在C中调用它的示例代码(我检查了它真的有用): struct PrecursorInfo{ double dIsolat
我想使用COM互操作从C#调用COM组件中的方法.这是方法签名:
long GetPrecursorInfoFromScanNum(long nScanNumber,LPVARIANT pvarPrecursorInfos,LPLONG pnArraySize) 这是在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); // Access the safearray buffer BYTE* pData; SafeArrayAccessData(vPrecursorInfos.parray,(void**)&pData); for (int i=0; i < nPrecursorInfos; ++i) { // Copy the scan information from the safearray buffer PrecursorInfo info; memcpy(&info,pData + i * sizeof(MS_PrecursorInfo),sizeof(PrecursorInfo)); } SafeArrayUnaccessData(vPrecursorInfos.parray); } 以下是导入COM组件的类型库后的相应C#签名: void GetPrecursorInfoFromScanNum(int nScanNumber,ref object pvarPrecursorInfos,ref int pnArraySize); 如果我没有弄错,我需要为pvarPrecursorInfos传入null,以使COM interop将其编组为预期的VT_EMPTY变体.当我这样做时,我得到一个SafeArrayTypeMismatchException – 并不奇怪,看看如何在样本中处理结果.所以我试图使用自定义封送器.由于a不能改变组件本身,我试着用这种方式介绍它: [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); } TypeLibType和DispID属性与原始版本中的相同.这可以调用MyMarshaller.GetInstance()方法,但我没有在MyMarshaller.NativeToManaged中获得回调.而是报告访问冲突.那么这是一种可靠的方法吗?如果是的话 – 我怎样才能让它发挥作用?如果不是:还有其他选择吗? (只是一个脚注:理论上我可以尝试使用托管C本地调用组件.但是,有很多其他方法可以与COM互操作一起使用,所以我非常希望坚持使用C#,如果有的话无论如何.) 解决方法
由于有人要求,这是我在Managed C中的解决方案.
array<PrecursorInfo^>^ MSFileReaderExt::GetPrecursorInfo(int scanNumber) { VARIANT vPrecursorInfos; VariantInit(&vPrecursorInfos); long nPrecursorInfos = -1; //call the COM component long rc = pRawFile->GetPrecursorInfoFromScanNum(scanNumber,&nPrecursorInfos); //read the result //vPrecursorInfos.parray points to a byte sequence //that can be seen as array of MS_PrecursorInfo instances //(MS_PrecursorInfo is a struct defined within the COM component) MS_PrecursorInfo* pPrecursors; SafeArrayAccessData(vPrecursorInfos.parray,(void**)&pPrecursors); //now transform into a .NET object array<PrecursorInfo^>^ infos = gcnew array<PrecursorInfo^>(nPrecursorInfos); MS_PrecursorInfo currentPrecursor; for (int i=0; i < nPrecursorInfos; ++i) { currentPrecursor = pPrecursors[i]; infos[i] = safe_cast<PrecursorInfo^>(Marshal::PtrToStructure(IntPtr(¤tPrecursor),PrecursorInfo::typeid)); } SafeArrayUnaccessData(vPrecursorInfos.parray); return infos; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |