绝对COM混淆-具有早期绑定的C#互操作
作者:互联网
我整天都在与VStudio,Google和其他各种工具和网站进行斗争,却找不到解决方案-帮助!
我有两个COM接口(纯COM,无ATL):
IMyClassFactory和IMyClass及其相应的实现
我想通过C#BUT使用它们,而不用regsvr32注册COM服务器.
我使用CoRegisterClassObject公开了类工厂,并且可以使用非托管代码通过CoCreateInstance成功创建IMyClass对象.
所以C#互操作…
我使用tlbimp myComServer.tlb创建了一个.NET包装器,并将其加载为对C#客户端的引用.
然后,当我尝试创建IMyClass实例时,我得到:
An unhandled exception of type 'System.InvalidCastException' occurred in COMTestClient.exe
Additional information: Unable to cast COM object of type 'MyComServerLib.MyClass' to interface type 'MyComServerLib.IMyClass'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{9F8CBFDC-8117-4B9F-9BDC-12D2E6A92A06}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
现在,我向QueryInterface添加了跟踪,返回E_NOINTERFACE的唯一情况是它请求与Marshal相关的任何接口或IManagedObject.
我该如何解决??
编辑:我的IDL文件:
import "unknwn.idl";
[
object,
uuid(...),
nonextensible,
pointer_default(unique)
]
interface IMyClass : IUnknown
{
HRESULT(SetFirstNumber)(long nX1);
HRESULT(SetSecondNumber)(long nX2);
HRESULT(DoTheAddition)([out,retval] long *pBuffer);
};
[
uuid(...)
]
library MyLib
{
importlib("stdole2.tlb");
[
uuid(...)
]
coclass IMyClassImpl
{
[default] interface IMyClass;
};
}
解决方法:
您需要允许对接口进行编组(即,通过在.idl文件中将其标记为“非本地”,以便使其最终出现在类型库和代理/存根中),或聚合自由线程如果你那样走的话.
为了汇总FTM,我做了这样的事情:
#define DECLARE_FTM() \
protected: CComPtr<IUnknown> _m_Marshal; \
DECLARE_GET_CONTROLLING_UNKNOWN() \
public: HRESULT FinalConstruct() \
{ return CoCreateFreeThreadedMarshaler(GetControllingUnknown(),&_m_Marshal); }
#define COM_INTERFACE_ENTRY_FTM() COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal,_m_Marshal.p)
然后,在您的COM映射中:
BEGIN_COM_MAP(Blah)
COM_INTERFACE_ENTRY(IBlah)
COM_INTERFACE_ENTRY_FTM()
END_COM_MAP()
DECLARE_FTM()
我注意到您没有使用ATL之类的东西-您需要对其进行修改,以便查询IMarshal时QueryInterface实现返回FTM指针.
请注意,对FTM进行汇总并不是一件轻而易举的事情-它做出了许多不安全的假设,这些假设并不总是有效的.例如,您的类不能使用本身不是自由线程的任何接口.
另一个选择基本上是如@ [Franci Penov]所说的,您需要确保可以对您的接口进行编组.以我的理解,有一个标准的编组器,可以封送类型库中的任何接口,或者您(即Midl编译器或多或少自动执行此操作)可以使代理/存根dll(或合并代码)代理/存根到您自己的dll中),可以为您封送它.
文章here describes the process of building and registering the proxy/stub更详细.
标签:com,interop,com-interop,c 来源: https://codeday.me/bug/20191024/1920064.html