2011-01-13 52 views
4

我正在考慮在C++/CLI中移植一個應用程序C/C++。用.NET連接C/C++

主要我想利用反射,XML序列化的可能性以及Microsoft提供的.NET框架中的所有功能(甚至可能是單聲道)。

有問題的項目沒有大量使用STL,應用程序對象大多是靜態分配的。很多代碼是用C編寫的,另一個是用C++實現的。

問題是代碼非常非常非常「長」:這是現有代碼轉換所需時間的問題,因此它可以正常運行。

我試圖創建一個在/ clr中使用flag編譯的C++項目,畢竟沒那麼糟糕。您可以保留現有代碼C++,但同時使用「managed」類,甚至可以從C++類方法訪問「受管理」對象。

,我發現很少,但讓我疑惑這個「移民」這個漏洞......

要充分利用使用反射數據序列化的,我所有的數據結構應加以管理。非託管類不能聲明由某種類型的託管類定義的字段。爲了解決這個問題,如果一個類被轉換,以便它被垃圾收集器管理,那麼每個聲明該類型成員的類都將被管理。

在引入托管類時可能遇到什麼困難?

嗯,我在想:

  • 字符串管理(我討厭打電話AllocaHGlobal轉換System.String字符 *每次我需要它(例如,作爲函數參數)
  • 陣列管理古典陣列(轉換爲cli來::陣列)
  • (已經提到過)混合管理和非管理類
  • 異常處理
  • 崩潰(核心)創建轉儲如何影響
  • ...任何其他,我都沒有想過尚未...

回答

2

非託管班可以設法成員。訣竅是使用gcroot模板。看看這裏

http://weblogs.asp.net/kennykerr/archive/2005/07/12/Mixing-Native-and-Managed-Types-in-C_2B002B00_.aspx

更多地瞭解它。

編輯:作爲對其他一些問題的迴應:當你有一個工作的C++代碼庫,這個代碼庫如此之大以至於你必須期望來自生產的變更請求,而你正在使用C++/CLI端口,恕我直言,最好的辦法是避免有相同的代碼庫的兩個副本。相反,嘗試使用C++和C++/CLI編寫相同的代碼,使用#ifdef,宏,生成器等。我知道這是可能的,因爲這正是我們前一段時間移植一個大約120.000行碼。

對於字符串轉換,我們使用此代碼:

typedef System::String^ SysString; 

inline SysString Std2Sys(const std::string &s) 
{ 
    return gcnew System::String(s.c_str()); 
} 

inline std::string Sys2Std(SysString ss) { 
    using namespace System::Runtime::InteropServices; 
    const char* chars = 
     (const char*)(Marshal::StringToHGlobalAnsi(ss)).ToPointer(); 
    std::string s = chars; 
    Marshal::FreeHGlobal(System::IntPtr((void*)chars)); 
    return s; 
} 

(表現從來沒有與我們的情況的問題,可能是你的不同,但不要試圖如果有任何優化沒有任何需要)。

1

Doc Brown makes a good point about gcroot。相反,託管類可以指向本地「子對象」。

通常需要在auto_ptrshared_ptr上創建互操作變體,以便編譯器在父對象死亡時生成所有樣板以廢棄子對象,即使是託管和非託管混合。

如果字符串轉換讓你瘋狂,你可能想看看C++/CLI附帶的marshall_as模板。

+0

很高興知道,但marshall_as包含從VS 2008開始。嘆息。 – Luca 2011-01-13 22:06:02