我一直在与VStudio,Google以及其他各种工具和网站进行斗争,但没有找到任何解决方案 - 帮助!!
我有两个COM接口(纯COM,没有ATL):
IMyClassFactory和IMyClass以及相应的实现
我想在没有使用regsvr32注册COM服务器的情况下从C#BUT使用它们。 我用CoRegisterClassObject公开了Class Factory,我可以用非托管代码用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;
};
}
答案 0 :(得分:4)
您需要允许对您的接口进行编组(即,在.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]所说,你需要确保你的界面能够被编组。我理解它的方式,有一个标准的marshaller能够编组类型库中的任何接口,或者你(也就是midl编译器或多或少地自动执行)可以创建一个proxy / stub dll(或合并代码)代理/存根到你自己的dll),它可以为你编组。
本文here describes the process of building and registering the proxy/stub更详细。
答案 1 :(得分:1)