2011-11-09 92 views
1

我相信我的問題的答案是已經存在於此論壇上的許多線程的組合。也許你可以幫我把這些東西放在一起。C++接口的.NET實現,暴露給COM

所以我的挑戰是,我有一些C++代碼實現,看起來像這樣的接口:

interface ItsSupplier : IDispatch { 
    [propget, id(1), helpstring("property name") HRESULT Name([out, retval] BSTR* pVal); 
} 

實現此接口的DLL,是在第三方軟件可用的插件。 我想製作一個用.NET編寫的插件。 由於使用插件的軟件不是.NET,我假定該DLL必須是COM對象。

這是我在.NET中如何去做的。

[Guid("xxxx")] 
public interface ItsSupplier { 
    [DispId(1)] 
    [return: MarshalAs(UnmanagedType.Bstr)] 
    string Name { get; } 
} 

[Guid("xxxx"), 
ClassInterface(ClassInterfaceType.AutoDispatch), 
ComSourceInterfaces(typeof(ItsSupplier))] 
    public class SupplierClass : ItsSupplier 
    { 
     public string { get { return "someName"; } } 
    } 
} 

在項目設置下,我已選中「Register for COM interorp」。

構建之後我運行「regasm testDll.dll」

我的問題是...

是它定義ItsSupplier接口自己的路嗎?我的意思是,這是第三方軟件期望的接口,那麼它將不得不在其他地方引用?

我說得沒錯,談到COM互操作部分?

我希望我解釋這個吧:)

乾杯 /托馬斯

----------------編輯響應後的Hans --- ---------------------

當我構建tlb文件並在Oleview中查看原始版本和我的版本時,這就是我所得到的。

這裏是原來的接口插件的樣子在OLEVIEW:

[ 
    odl, 
    uuid(370B4079-40BB-47C9-B797-33B3B5422685), 
    helpstring("ItsSupplier Interface"), 
    dual, 
    oleautomation 
] 
interface ItsSupplier : IDispatch { 

這裏是我的樣子:

[ 
    odl, 
    uuid(370B4079-40BB-47C9-B797-33B3B5422685), 
    version(1.0), 
    dual, 
    oleautomation, 
    custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "COMDLL.ItsSupplier")  

] 
interface COMDLL_ItsSupplier : IDispatch { 

的 「COMDLL」 我的Visual Studio項目的名稱。你認爲重要嗎?

/Thomas

回答

3

不,很多細微的錯誤會讓你陷入困境。首先,C++接口聲明一個雙接口,通過IDispatch支持早期綁定和後期綁定。你必須使用[InterfaceType]屬性在.NET中得到相同的:

[ComVisible(true)] 
[Guid("xxxx")] 
[InterfaceType(ComInterfaceType.InterfaceIsDual)] 
public interface ItsSupplier { 
    [DispId(1)] 
    string Name { get; } 
} 

請務必使用確切 GUID相同,它是不是在你的代碼片段可見。 [MarshalAs]屬性是不必要的,該字符串已經作爲BSTR編組。

接下來是班級。你做不是想暴露類的實現。這迫使客戶端代碼也要小心System.Object,它是所有.NET類的基類。它將出現在類型庫中。使用[ComSourceInterfaces]不正確,應該只應用於事件的調度接口。

[ComVisible(true)] 
[Guid("xxxx")] 
[ClassInterface(ClassInterfaceType.None)] 
public class SupplierClass : ItsSupplier 
{ 
    public string Name { 
     get { return "someName"; } 
    } 
} 

再次使用確切相同的GUID在IDL文件使用。接下來是註冊。使用「註冊COM互操作」選項是好的,但然後做而不是再次運行Regasm.exe。你會搞砸了註冊。如果您更喜歡手動註冊,那麼請始終使用/ codebase選項,以免將程序集安裝到GAC中。

最終的檢查,你得到一切正確的是與Tlbexp.exe創建類型庫,並與Oleview.exe,文件+查看Typelib查看它。它應該與您的IDL完全匹配。

+0

嘿漢斯 非常感謝您的意見,這肯定確實澄清了一些事情。 至於查看Oleview中的Tlb文件,這太棒了! 請看看我的答案在哪裏得到了我。 – ThomasVestergaard

+0

這很好,只是由tlbexp.exe添加了一些額外的屬性。你無法獲得[幫助]。 –

+0

另一個更新。請再次看看頂部:) – ThomasVestergaard