[英]Absolute COM Confusion - C# interop with early-binding
我一直在與VStudio,谷歌以及其他各種工具和網站進行斗爭,但沒有找到任何解決方案 - 幫助!
我有兩個COM接口(純COM,沒有ATL):
IMyClassFactory和IMyClass以及相應的實現
我想在沒有使用regsvr32注冊COM服務器的情況下從C#BUT使用它們。 我使用CoRegisterClassObject公開了Class Factory,並且我可以從非托管代碼中使用CoCreateInstance成功創建IMyClass的對象。
所以C#interop ...
我使用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文件中將其標記為不是“本地”,以便它最終在類型庫中,在代理/存根中),或者聚合自由線程marshaller如果你這樣走。
為了聚合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),它能夠為你編組。
這篇文章更詳細地描述了構建和注冊代理/存根的過程 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.