2011-05-13 74 views
1

我們有執行高性能數據處理的傳統C++代碼(例如,從硬件設備饋入的大量數據以時間敏感的方式處理,以便顯示,轉換並傳輸到輔助存儲器)。C#和C++可以交互使用高性能代碼嗎?

我們對新的GUI和新實用工具(現有的GUI是C++ MFC和Qt)的C#/ .NET感興趣。當然,對於現有的系統,我們沒有.NET虛擬機的「語言翻譯」問題(現有代碼都是C++)。

經過大量研究和許多書籍,我不確定這可以有效地完成。可能的方法(我錯過任何?):

  1. 重寫一切都在.NET(不能 發生 - 太多的代碼,裸機設備訪問,時間敏感的重算法處理)
  2. 薄對於託管的託管 C++/CLI
  3. 厚適配器層適配層 C++/CLI
  4. 不要使用.NET(經理感到極大的悲傷 )

我們對(2)「精簡適配器層」的關注是,如果GUI可以(重新)使用「業務」層中的邏輯(許多屬性由算法派生),那將會很好,所以如果我們不公開/包裝C++類,很多GUI邏輯將僅複製業務層中現有的C++邏輯。我們對(3)「粗適配器層」的擔憂是,用C#類來包裝每個C++類似乎非常繁瑣(昂貴),並且一些書籍表明跨該邊界的裝箱/拆箱訪問似乎暗示了這一點方法是不可行的/令人望而生畏的(除了微不足道的設計之外,它的表現令人望而卻步)。

你如何在C++中實現的深富階級結構的頂部接口新的C#/。NET(GUI)?

回答

5

C++/CLI是完美的。託管/非託管翻譯沒有性能問題,因爲C++/CLI使用.NET運行時引擎自身使用的相同的優化調用技術來實現字符串連接等高性能方法。

當您在.NET和相同數據結構的本機版本之間來回複製數據時,會出現性能問題,但是您也會遇到同樣的問題。使用一個使用BSTR的庫,並使用std::string,緩慢的操作同樣明顯(與P/Invoke不同,後者試圖使這些翻譯變得透明,最終隱藏了過程中的性能問題)。

還有一些技巧可以用來克服這一點。例如,不是將std::vector複製到System::Collections::Generic::List中,而是實施從std::vector直接讀取的IEnumerator

當然,如果數據只是直接傳遞迴另一個C++函數,那麼根本沒有理由將其轉換爲託管類型。再一次,C++/CLI使保存格式變得簡單,P/Invoke試圖轉換背後的所有內容。

總之,「瘦」的C++/CLI包裝層是最好的選擇。

2

您對約束有正確的想法。跨越邊界是昂貴的,你不想爲細粒度的操作做到這一點。如何細粒度? 當然,這取決於

在理想的情況下,您的C++代碼被分層到一個理性的對象模型中,通過這個模型你可以爲一個更大粒度的操作放置一個COM層(或類似的)。舉一個例子,你不希望公開一個包含5個屬性的對象,並且每個對象都有一個setter/getter對,你會希望公開一個SetProperties()方法,該方法接受要設置的所有屬性的映射。這絕不是唯一需要注意的情況;這只是一個如何將自己傾向於更大粒度操作的例子。

關於COM - 這很好,但當然不是必需的。使用COM強制執行一項規定,因爲您需要正式定義COM接口中的操作。如果沒有COM提供的正式實施,你的團隊可能會「作弊」 - 並在各層之間暴露無數的戰術集成點,這可能導致性能問題。

如果你有紮實的項目管理和優秀的團隊成員,那麼你可以做的這些項目標準的執行不依賴於COM的手續。在C#中定義您自己的包裝類,通過它發生所有跨界。

底線,我懷疑,是你不知道究竟是正確的決定,直到你玩它,並對其進行測試。

找幾個團隊成員,好開發人員,讓他們建立兩個不同選項的原型。例如,薄與厚,這些術語的確切含義由您定義。給他們3周左右的時間把東西放在一起。然後衡量他們的生產力和績效,並據此作出決定。