我整天都在与 VStudio、Google 和各种其他工具和网站作斗争,但没有找到解决方案 - 求助!!
我有两个 COM 接口(interface)(纯 COM,无 ATL):
具有相应实现的 IMyClassFactory 和 IMyClass
我想在 C# 中使用它们,但不使用 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 相关的接口(interface)或 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;
};
}
最佳答案
您需要允许您的接口(interface)被编码(即,通过在 .idl 文件中将其标记为非“本地”,以便它最终出现在类型库和代理/ stub 中),或聚合自由线程编码器,如果你这样做的话。
为了聚合 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 等 - 您需要修改它,以便您的 QueryInterface 实现在查询 IMarshal 时返回 FTM 指针。
请注意,聚合 FTM 并不是一件轻而易举的事情 - 它会做出一些并不总是有效的不安全假设。例如,您的类不能使用任何本身不是自由线程的接口(interface)。
另一种选择基本上如@[Franci Penov] 所说,您需要确保您的接口(interface)能够被编码。按照我的理解,有一个标准编码器能够编码类型库中的任何接口(interface),或者您(即 midl 编译器或多或少地自动执行)可以制作代理/ stub dll(或合并代码用于将代理/ stub 放入您自己的 dll 中),它能够为您编码它。
本文here describes the process of building and registering the proxy/stub更详细。
关于c# - 绝对 COM 混淆 - C# 与早期绑定(bind)的互操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1528503/