2011-11-30 38 views
0

我已經繼承了一箇舊的MFC/Win32 C++應用程序,它是我不應該編輯的源代碼。在舊的MFC/Win32應用程序上使用C++ interop時遇到錯誤

此MFC應用程序需要託管一箇舊的MFC/Win32 C++ DLL。此DLL還嘗試通過混合模式包裝器對託管的C++/CLI DLL進行函數調用。我知道這聽起來有點混亂,所以這裏是我的意思的示意圖:

Old MFC/Win32 Application (NO CLR) 

    ---> Hosting old MFC/Win32 DLL (NO CLR) 

       ---> Making function calls to Mixed-Mode wrapper (CLR) 

           ---> Sending function calls to C++/CLI DLL (CLR) 

我的問題目前是,當我嘗試裝入C++/CLR包裝類的對象,讓我們說WrapperClass WC;,在MFC/Win32應用程序遇到「未處理的異常」。

我有一種感覺,我可能需要以某種方式託管CLR在一個單獨的過程,以便能夠使對象。這是正確的想法嗎?或者我完全不在這裏?

代碼編譯時間,這隻發生在運行時。

任何想法?

這裏是我試圖運行的代碼的一個例子:

MFC /的Win32 DLL

#include "WrapperClass.h" 

BOOL Test::bTest() //This function is called elsewhere within MFC/Win32 DLL 
{ 
    DWORD dwTest; 

    WrapperClass WC; //Unhandled exception here! 

    return WC.FunctionToCall(dwTest); //FunctionToCall is a BOOL 
} 

混合模式封裝類

BOOL WrapperClass::FunctionToCall(DWORD dw) 
{ 
    GCHandle h = GCHandle::FromIntPtr(IntPtr(m_impl)); //m_impl def'd as void * 
    CPPCLIClass^ CCC = safe_cast<CPPCLIClass^>(h.Target); 

    return (BOOL)CCC->FunctionToCall(dw); 
} 

C++/CLI DLL

bool CPPCLIClass::FunctionToCall(UInt32 ui32) 
{ 
    if (ui32 == 42) 
    { 
     return true; 
    } 
} 

UPDATE: 我已經成功地哄一個真正的例外出來的方案。我現在接收System.IO.FileNotFound異常附加信息說明:

An unhandled exception of type 'System.IO.FileNotFoundException' occured in 
Unknown Module. 

Additional information: Could not load file or assembly 'CPPCLIProject, 
Version=1.0.4351.29839, Culture=neutral, PublicKeyToken=null' or one of its 
dependencies. The system cannot find the file specified. 

這是否意味着什麼?我明白,它顯然無法找到CPPCLIProject(注意:這不是包裝項目),但如果我從混合模式包裝器鏈接.lib文件,那麼我將如何不接收鏈接器錯誤?

+0

您在C++/CLR和C++/CLI之間的區別是什麼?前者只是後者的常見拼寫錯誤,即它們是同一件事。 – ildjarn

+0

我應該說混合模式DLL而不是C++/CLR,我現在要解決這個問題。請參閱更新的問題:) – Brutick

回答

2

您確定WrapperClass::FunctionToCall()的執行沒有拋出異常嗎?它看起來像緩存CLR對象的內存位置,然後嘗試調用其中一個成員。我認爲CLR可以隨意移動物體,因此您可能試圖使用已移動的對象。

如果您將WrapperClass::FunctionToCall()的實現更改爲簡單的操作(即創建一個CLR對象,調用成員函數),您仍然會得到相同的未處理異常嗎?

UPDATE:CPPCLIProject中的哪個類是CPPCLIClass?假設這個項目代表了C++/CLI DLL,這聽起來像是在它需要調用你的類時找不到程序集來加載它。

該組件在磁盤上相對於應用程序的其餘部分在哪裏?如果你的根EXE是非託管的(聽起來是這樣,因爲它是MFC/Win32),那麼CLR會在EXE的目錄和GAC中查找以加載程序集(我不認爲它看起來在Path中,但我不積極)。

因此,如果CPPCLIProject與EXE不在同一目錄中,那可能是您的問題。

+0

「WrapperClass :: FunctionToCall」的前兩行實際上是Microsoft對這種類型的interop的實現的一部分,我所做的只是將它自定義爲使用與我一起工作的相同類名。說實話,我不確定他們在那裏完成了什麼,但它似乎工作(至少在他們的示例解決方案中)。 – Brutick

+0

啊我明白你的意思了。目前,雖然我不能爲我的生活弄清楚爲什麼CPPCLIProject沒有創建一個.lib文件供我鏈接!我嘗試了幾種不同的方法來強制.lib文件,但它似乎不想爲我創建一個:( – Brutick

+0

啊!我已經發現問題是我試圖鏈接CPPCLIProject的.lib文件不應該生成,解決方案如上所述,所有dll必須與MFC應用程序位於同一文件夾中!感謝Andy :) – Brutick

1

你最好的賭注是

  • 運行調試程序下
  • 開啓所有(第一次機會)破例外
  • 跟蹤/(調試信息的調試會話中添加額外的DLL)斷言所有HRESULT代碼
  • 一般試圖抓住
    • C++異常(try/catch ...)
    • 個的Windows結構化異常(IIRC _ 嘗試/ _catch,但see MSDN

的想法是將 '未知異常' 轉換成 '已知的異常'。

通常來說,不需要將CLR部分託管在進程外。這是一個混合模式DLL。如果這是遺留代碼,那麼您可能會遇到複雜的運行時依賴關係混合,我們應該說可能會發生衝突。


另外的想法:

如果我理解正確的話,你可以選擇重新編譯所有源(只是不觸及原有的代碼庫?)。如果是,請確保所有代碼都是針對運行時庫的相同版本(請考慮Service Pack)進行編譯並鍵入(認爲靜態與動態/多線程/調試)。

當你正在檢查另外的途徑,保持對潛在衝突的依賴注視

  • ATL服務器庫
  • MFC庫(再次靜態VS動態/多線程/調試口味)。
+0

我試圖重建MFC/Win32應用程序,顯然,它變得更糟。現在它甚至不會像以前那樣加載到MFC DLL中,但它會在我對它進行任何更改之前加載MFC DLL的版本。 :( – Brutick

+0

看來,在進一步挖掘到應用程序的源代碼之後,應用程序試圖在MFC DLL上運行一個'LoadLibrary()',最終返回NULL。是否有任何可能的解釋說明爲什麼會發生這種情況只有使用我的較新版本的MFC DLL而不是舊版本(原始版本)? – Brutick

+0

是的,當然,你可能正在運行其中一個鏈接到msvcrt * .dll的MFC版本,**必須加載/初始化這是艱難的事情 - 無論如何要記住它,你應該能夠找到你的出路(MSVCRT + manifest +你的運行時名稱(例如vcredist2008等))並學習更多關於並行緩存和SxS版本策略比您想要知道的更多。 – sehe

相關問題