2011-11-17 47 views
12

我正在封裝一個MFC擴展DLL(MFCXDLL_2)以使其功能可供C#程序員使用。本機應用程序中的C#.NET用戶控件。資源鏈問題

該包裝是一個「使用共享MFC DLL常規DLL」與「公共語言運行庫支持(/ CLR)」。 (混合模式)。

應該可用的MFCXDLL_2中的類在MFCXDLL_3中進行了修飾。

我遇到的情形是,MFCXDLL_2是從本地應用程序運行的C#.NET用戶控制使用的情況下。

另一個MFC擴展DLL -MFCXDLL_1,裏面的本地應用程序也使用MFCXDLL_2,這造成麻煩。

當我啓動本機應用程序時,它將隱式加載MFCXDLL_2。

當我加載.NET用戶控件時,將根據http://msdn.microsoft.com/en-us/library/ksa99t88.aspx「在常規DLL中使用數據庫,OLE和套接字擴展DLL」中的建議,再次明確加載相同的MFCXDLL_2。

兩個本機代碼和.NET用戶控制實例相同的類型,並調用在MFCXDLL_2相同的方法。

的方法,解串數據(通過共享存儲器接收的)和去串行化的數據返回給調用者。直到我加載.NET用戶控件時,這從原生代碼很好地工作。

加載.NET用戶控件後,反序列停止從本機代碼的工作,但是從.NET用戶控件調用時,它的偉大工程。

我將WinDbg附加到原生應用程序的調試版本並運行我的方案。 WinDbg在反序列化過程中發現如下:

「警告:無法從存檔加載。類未定義。 CArchive的例外:badClass」

我覺得這裏有一些資源問題,所以我運行本地應用程序加載MFCXDLL_2的發行版本的發行版本。然後,我加載了.NET用戶控件的調試版本 - 它再次將調試版本的MFCXDLL_2加載到本機應用程序中。

然後,一切都很好。由本地代碼加載的MFCXDLL_2的一個發行版本和由.NET用戶控件加載的MFCXDLL_2的一個調試版本 - 全部在本機應用程序內運行。

那麼發生了什麼?是否無法從例如相同的MFCXDLL訪問一個擴展DLL和一個常規DLL在同一個應用程序中的同一時間?
資源鏈是否以某種方式被破壞? 什麼是可能的解決方案?

下面是該MFCXDLL_2 DLL的加載
一些代碼在本機應用程序啓動MFCXDLL_2的DLLMain被稱爲:

static AFX_EXTENSION_MODULE MFCXDLL_2 = { NULL, NULL }; 
static CDynLinkLibrary* gpDynLinkLibrary = NULL; 

extern "C" int APIENTRY 
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID) 
{ 
    if (dwReason == DLL_PROCESS_ATTACH) 
    { 
     // Extension DLL one-time initialization 
     AfxInitExtensionModule(MFCXDLL_2, hInstance); 

     // Insert this DLL into the resource chain 
     gpDynLinkLibrary = new CDynLinkLibrary(MFCXDLL_2); 
    } 
    else if (dwReason == DLL_PROCESS_DETACH) 
    { 
     if (gpDynLinkLibrary) 
     { 
       delete gpDynLinkLibrary; 
       gpDynLinkLibrary = NULL; 
     } 
     // Terminate the library before destructors are called 
     AfxTermExtensionModule(MFCXDLL_2); 
    } 
    return 1; // ok 
} 

當。NET用戶控制被裝載時,MFCXDLL_2 DLL被再次加載:

//============================================================== 
// Exported DLL initialization to run in context of Regular DLL. 
// Must be called in InitInstance 
// BOOL CYourRegularDLLApp::InitInstance() 
//============================================================== 
extern "C" _declspec(dllexport) CDynLinkLibrary* WINAPI InitMFCXDLL_2FromRegularDLL() 
{ 
    if (gpDynLinkLibrary) 
    { 
     delete gpDynLinkLibrary; 
     gpDynLinkLibrary = NULL; 
    } 
    // Create a new CDynLinkLibrary for this Regular DLL 
    return new CDynLinkLibrary(MFCXDLL_2); 
} 

的反序列化碼內MFCXDLL_2

CMyClass* pMyclass = NULL; //CObject derived serializeable class 
    BYTE *pBuf  = pGlobalCom->GetBuffer(); //Buffer with serialized CMyClass 
    int nBufSize = pGlobalCom->GetSize(); //Size of buffer 

    CMemFile mf; 
    mf.Attach(pBuf,nBufSize); 

    CArchive ar(&mf, CArchive::load); //「Warning: Cannot load CMyClass from archive. Class not defined.CArchive exception: badClass.」 

    ar >> pMyclass; //CArchive exception thrown 
    ar.Close(); 
    mf.Detach(); 

所述的圖像顯示的DLL之間的關係。

enter image description here

回答

1

我認爲,你可以在這裏有些混亂,你的包裝正在做。

您可以使用DLLImport語句從.NET代碼中調用非託管C++ DLL。

我會建議你創建一個C#類庫項目,這將是你的非託管的DLL,MFCXDLL包裝DLL。

您可能不會能夠將DLL添加爲引用資源,但您應該創建一個項目文件夾,將其存儲並添加爲項目文件,設置爲Copy Local True建成。您還需要將MFCXDLL在同一文件夾中引用的任何DLL也設置爲「複製本地」。

然後,您從所有基於.NET的代碼中引用您的NET DLL。

Here是包裝過程的一個例子。

編輯

我有一張支票,是我用的是使用MFC的共享庫的非託管C++ DLL。下面是我使用的代碼的削減版本。(有些類名稱已更改由於保密協議。)

using System.Collections.Generic; 
    using System.Runtime.InteropServices; 

    public class WrapperClass 
    { 
     [DllImport("some.dll", EntryPoint = "WriteDataCard", SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.VariantBool)] 
     public static extern Boolean WriteDataCard(Byte nComPort, bool bInitialize, bool bCardFeeder, [In] Byte[] bytesData, Byte dataSize, bool bTestKey); 

     [DllImport("some.dll", EntryPoint = "ReadDataCard", SetLastError=true)] 
     [return: MarshalAs(UnmanagedType.VariantBool)] 
     public static extern Boolean ReadDataCard(Byte nComPort, Boolean bInitialize, Boolean bCardFeeder, [Out] Byte[] bytesData, Byte dataSize); 

    } 
+0

我可以n要看到一個C#包裝將如何解決這個問題。 它如何解決問題? 我遵循文章http://www.codeguru.com/cpp/cpp/cpp_managed/interop/article.php/c6867中給出的模式。 託管和非託管世界之間的實際橋樑是混合模式DLL。包裝器只裝飾我想要爲.NET用戶控件顯示的類。 – kjella

+0

你說得對。照片錯了。這當然是「常規DLL使用共享的MFC DLL」,這是包裝。我現在改變了圖片。 MFCXDLL_3裝飾MFCXDLL_2中的一些類,併爲用戶控件創建必要的功能性。 – kjella

+0

您正在查看的CodeGuru模式是從2004年開始的。我非常確定它不再適用(至少在NET 3.5以上版本中)。我可以仔細檢查我在另一臺機器上的代碼,稍後會回發。 – ChrisBD

相關問題