2011-11-17 8 views
12

मैं सी # प्रोग्रामर के लिए अपनी कार्यक्षमता उपलब्ध कराने के लिए एक एमएफसी एक्सटेंशन DLL (MFCXDLL_2) को लपेट रहा हूं।सी # .NET उपयोगकर्ता नियंत्रण मूल ऐप के अंदर। संसाधन श्रृंखला की समस्याएं

रैपर "सामान्य भाषा रनटाइम समर्थन (/ clr)" के साथ "साझा एमएफसी डीएलएल का उपयोग कर नियमित डीएलएल" है। (मिश्रित मोड)।

एमएफसीएक्सडीएलएल_2 में कक्षाएं उपलब्ध होंगी जो एमएफसीएक्सडीएलएल_3 में सजाए जाएंगी।

जिस परिदृश्य का मैं अनुभव कर रहा हूं वह वह मामला है जहां MFCXDLL_2 का उपयोग किसी मूल अनुप्रयोग में चल रहे सी # .NET उपयोगकर्ता नियंत्रण से किया जाता है।

एक अन्य एमएफसी एक्सटेंशन DLL -MFCXDLL_1- देशी एप्लिकेशन के अंदर भी MFCXDLL_2 का उपयोग करता है और यह कारण परेशानी का कारण बनता है।

जब मैं मूल आवेदन शुरू करता हूं तो यह निश्चित रूप से MFCXDLL_2 को लोड करेगा।

जब मैं .NET उपयोगकर्ता नियंत्रण लोड करता हूं, तो उसी MFCXDLL_2 को http://msdn.microsoft.com/en-us/library/ksa99t88.aspx में सलाह के अनुसार स्पष्ट रूप से लोड किया जाता है, "नियमित डीएलएल में डेटाबेस, ओएलई और सॉकेट एक्सटेंशन डीएलएल का उपयोग करना"।

देशी कोड और .NET उपयोगकर्ता नियंत्रण दोनों एक ही कक्षा के प्रकार को तुरंत चालू करते हैं और उसी विधि को MFCXDLL_2 में कॉल करते हैं।

विधि डेटा को साझा करता है (साझा स्मृति से प्राप्त) और कॉलर को डी-सीरियलाइज्ड डेटा देता है। जब तक मैं .NET उपयोगकर्ता नियंत्रण लोड नहीं करता तब तक यह देशी कोड से बहुत अच्छा काम करता है।

.NET उपयोगकर्ता नियंत्रण लोड करने के बाद, डी-सीरियलाइजिंग मूल कोड से काम करना बंद कर देता है लेकिन .NET उपयोगकर्ता नियंत्रण से कॉल होने पर यह बहुत अच्छा काम करता है।

मैंने मूल अनुप्रयोग के डीबग संस्करण में WinDbg संलग्न किया और अपना परिदृश्य चलाया। डी-सीरियलाइजेशन के दौरान निम्नानुसार WinDbg पाया गया:

"चेतावनी: संग्रह से लोड नहीं हो सकता है। कक्षा परिभाषित नहीं है। कैरचिव अपवाद: badClass। "

मुझे लगता है कि यहां कुछ संसाधन समस्याएं हैं इसलिए मैं एमएफसीएक्सडीएलएल_2 के रिलीज संस्करण को लोड करने वाले देशी एप्लिकेशन का रिलीज़ संस्करण चलाता हूं। फिर मैं .NET उपयोगकर्ता नियंत्रण का डीबग संस्करण लोड करता हूं - जो फिर से मूल अनुप्रयोग में MFCXDLL_2 के डीबग संस्करण को लोड करता है।

तब सबकुछ बढ़िया काम करता है। मूल कोड द्वारा लोड किए गए MFCXDLL_2 का एक रिलीज़ संस्करण और .NET उपयोगकर्ता नियंत्रण द्वारा लोड MFCXDLL_2 का एक डीबग संस्करण - मूल एप्लिकेशन के अंदर चल रहा है।

तो क्या हो रहा है? क्या एमएफसीएक्सडीएलएल को उदाहरण से एक्सेस करना संभव नहीं है एक ही आवेदन में एक ही समय में एक विस्तार डीएलएल और नियमित डीएलएल?
क्या संसाधन श्रृंखला किसी तरह से नष्ट हो गई है? संभावित समाधान क्या हैं?

यहाँ कुछ दिखा कैसे 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 
} 

है।नेट उपयोगकर्ता नियंत्रण लोड किया जाता है, 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); 
} 

deserialize कोड 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(); 

छवि DLLs के बीच संबंधों को प्रदर्शित करते हैं।

enter image description here

उत्तर

1

मुझे लगता है कि आप अपने आवरण कर रहा है के रूप में कुछ भ्रम की स्थिति यहाँ हो सकता है।

आप DLLImport कथन का उपयोग कर .NET कोड के भीतर से अप्रबंधित C++ DLL को कॉल कर सकते हैं।

मैं सुझाव दूंगा कि आप एक सी # क्लास लाइब्रेरी प्रोजेक्ट बनाएं जो आपके अप्रबंधित डीएलएल, एमएफसीएक्सडीएलएल के लिए रैपर डीएलएल होगा।

शायद आप एक संदर्भित संसाधन के रूप में डीएलएल को जोड़ने में सक्षम नहीं होंगे, लेकिन आपको एक प्रोजेक्ट फ़ोल्डर बनाना चाहिए जिसमें आप इसे संग्रहीत करते हैं और इसे एक प्रोजेक्ट फ़ाइल के रूप में जोड़ते हैं, जब नेट क्लास लाइब्रेरी है तो स्थानीय ट्रू की प्रतिलिपि बनाने के लिए सेट करें बनाया। आप किसी भी डीएलएल को भी रखना चाहते हैं जो एमएफसीएक्सडीएलएल संदर्भ उसी फ़ोल्डर में भी स्थानीय कॉपी करने के लिए सेट है।

फिर आप अपने नेट डीएलएल को सभी नेट आधारित कोड से संदर्भित करते हैं।

Here रैपर प्रक्रिया का एक उदाहरण है।

संपादित

मैं एक चेक मिला है और हाँ मैं एक अप्रबंधित सी ++ DLL कि एक साझा पुस्तकालय के रूप में इस्तेमाल किया MFC इस्तेमाल किया है। यहां मेरे द्वारा उपयोग किए जाने वाले कोड का एक कट डाउन संस्करण है। (कुछ वर्ग नाम गोपनीयता समझौते के कारण बदल दिए गए हैं।)

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

मैं देख सकता हूं कि सी # रैपर समस्या को हल कैसे करेगा। यह समस्या का समाधान कैसे करता है? मैं लेख http://www.codeguru.com/cpp/cpp/cpp_managed/interop/article.php/c6867 में दिए गए पैटर्न का पालन कर रहा हूं। प्रबंधित और अप्रबंधित दुनिया के बीच वास्तविक पुल मिश्रित मोड डीएलएल है। रैपर केवल उन वर्गों को सजाने के लिए तैयार करता है जिन्हें मैं .NET उपयोगकर्ता नियंत्रण के लिए दिखाना चाहता हूं। – kjella

+0

आप सही हैं। तस्वीर गलत थी। यह निश्चित रूप से "साझा एमएफसी डीएलएल का उपयोग कर नियमित डीएलएल" है जो रैपर है। मैंने अब तस्वीर बदल दी है। MFCXDLL_3 MFCXDLL_2 में कुछ कक्षाओं को सजाने और उपयोगकर्ता नियंत्रण के लिए आवश्यक आवश्यक कार्यक्षमता बनाते हैं। – kjella

+0

कोडगुरु पैटर्न जिसे आप देख रहे हैं 2004 से है। मुझे पूरा यकीन है कि यह अब लागू नहीं होगा (कम से कम नेट 3.5 के बाद)। मैं कोड के साथ दोबारा जांच कर सकता हूं जो मेरे पास दूसरी मशीन पर है और बाद में पोस्ट करेगा। – ChrisBD

संबंधित मुद्दे