2009-08-13 19 views
14

में कनवर्ट करें मैंने सी ++/सीएलआई पॉइंटर को देशी सी ++ पॉइंटर में परिवर्तित करने की इस समस्या में भाग लिया है। पृष्ठभूमि है: मैं सी ++/सीएलआई का उपयोग कर एक विंडोज़ फॉर्म एप्लीकेशन लिख रहा हूं। एप्लिकेशन कई COM इंटरफेस में कॉल करता है। जब उदाहरण बनाकर COM इंटरफेस के माध्यम से एक वस्तु का (एक सी ++/CLR वर्ग के अंदर), मैं CoCreateInstance करने के लिए पिछले तर्क के रूप में (void**)(&provider) में गुजरती हैं, के रूप में:सी ++/सीएलआई पॉइंटर से देशी सी ++ पॉइंटर

HRESULT CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)(&provider)); 

हालांकि, मैं संकलक त्रुटि मिलती है: cli::interior_ptr<Type> से void ** में परिवर्तित नहीं कर सकते हैं। मैंने इसमें कुछ शोध किया है, और ऐसा लगता है कि यह सी ++ और सी ++/सीएलआई में विभिन्न प्रकार के पॉइंटर्स की समस्या है। किसी को इसके बारे में कोई जानकारी है, और शायद यह एक टिप तय किया जा सकता है कि इसे कैसे ठीक किया जा सकता है? अग्रिम में Thanx!

सबसे पहले, आपकी सभी मदद के लिए thanx!

जैसा कि फ्रीच ने सुझाव दिया था, मैंने pin_ptr का उपयोग करने की कोशिश की, लेकिन इसके बजाय संकलक ने interior_ptr से pin_ptr में परिवर्तित होने वाली समस्याओं के बारे में शिकायत की। मैं बजाय के रूप interior_ptr का उपयोग करने का प्रयास करें:

pin_ptr<void *> pinnedPtr = &provider; 
CoCreateInstance(CLSID_MSPRProvider, NULL, CLSCTX_LOCAL_SERVER, IID_IMSPRProvider, (void**)pinnedPtr); 

मैं interior_ptr से interior_ptr में परिवर्तित नहीं कर सकते हैं। यह सब interior_ptr को void** में परिवर्तित करने की समस्या को उबालता है। इस तरह: (void**)interiorPtr, जहां interiorPtr पाठ्यक्रम interior_ptr है। इसमें कोई विचार है?

उत्तर

10

मेरा मानना ​​है कि आपको पॉइंटर को 'पिन किया गया' (प्रबंधित कोड में) के रूप में चिह्नित करना होगा और फिर बाइट्स को कुछ अप्रबंधित स्मृति क्षेत्र में कॉपी करना होगा, और उसके बाद पॉइंटर का उपयोग करना होगा।

std::string managedStringToStlString(System::String ^s) 
{ 
    Encoding ^u8 = Encoding::UTF8; 
    array<unsigned char> ^bytes = u8->GetBytes(s); 
    pin_ptr<unsigned char> pinnedPtr = &bytes[0]; 
    return string((char*)pinnedPtr); 
} 

नोट मैं कैसे प्राप्त करने के लिए मिल गया है: उदाहरण के लिए, यहाँ जो एक UTF-8 एन्कोडेड अप्रबंधित std :: स्ट्रिंग के लिए एक प्रबंधित सिस्टम :: स्ट्रिंग के लिए सूचक धर्मान्तरित कोड मैं एक बार कहीं मिल गया का एक टुकड़ा है एक 'पिन किए गए' bytes सरणी सूचक GetBytes() समारोह से लौट आए, और उसके बाद डाली कि char* करने के लिए इसे std::string निर्माता को पार करने से पहले। मेरा मानना ​​है कि इससे बचने के लिए प्रबंधित स्मृति सबसिस्टम स्मृति में चारों ओर bytes सरणी चढ़ाव होता रहता है मैं एसटीएल स्ट्रिंग में बाइट्स को कॉपी कर रहा हूँ आवश्यक है।

आपके मामले में,

pin_ptr<void *> pinnedPtr = &provider; 
CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)pinnedPtr); 

साथ

CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)(&provider)); 

की जगह कोशिश करते हैं और देखते हैं कि क्या है कि काम करता है।

+0

यह खतरनाक प्रतीत होता है! मेरे पास पहले एक समान (या समान) स्थिति थी: मैंने एक पिन पॉइंटर बनाया और मूल सूचक (जैसे आप करते हैं) लौटा दिया, लेकिन फिर ऑब्जेक्ट स्थानांतरित हो गया क्योंकि फ़ंक्शन समाप्त हो गया और पिन किया गया पॉइंटर हटा दिया गया था, इसलिए ऑब्जेक्ट अब नहीं था पिन किया गया और मूल सूचक अवैध था! यह डिबगिंग के दौरान देखा जा सकता है या नहीं भी हो सकता है, लेकिन निश्चित रूप से यह आपके रिलीज़ संस्करण में होगा जब आप इसकी अपेक्षा नहीं करते हैं। –

+0

@TobiasKnauss 'std :: string :: string (const char *) 'कन्स्ट्रक्टर संदर्भित डेटा की एक प्रति बनाता है, इसलिए यह ठीक है अगर फ़ंक्शन से बाहर होने पर संदर्भित स्मृति अब पिन नहीं की जाती है। –

3

यह काफी समय है कि मैंने सी ++/सीएलआई का उपयोग किया, लेकिन मुझे लगता है कि आपको पॉइंटर पिन करना होगा।

+0

एक सुविधा टेम्पलेट बुलाया CLI :: pin_ptr के रूप में यह सुनिश्चित करना है कि बनाया गया है क्या ओ पी की जरूरत हो सकता है कि नहीं है करने के लिए एक प्रबंधित वस्तु के लिए एक सूचक कचरा कलेक्टर द्वारा चारों ओर स्थानांतरित नहीं किया जा रहा है। –

3

स्मृति CoCreateInstance करने के लिए कॉल से परे वैध होने की उम्मीद की ओर इशारा किया है()?

Frerich और अचिम का संकेत के रूप में, आप, स्मृति के लिए एक कच्चे सूचक प्राप्त कर सकते हैं स्मृति के डर के बिना दूसरी जगह किया जा रहा है, यह "पिन करते हुए" और एक इंटीरियर सूचक हो रही द्वारा। आप आम तौर पर pin_ptr टेम्पलेट (उदाहरण के लिए Frerich पोस्ट देखें) के साथ ऐसा कर।

हालांकि, pin_ptr जानबूझ स्टैक पर केवल प्रयोग करने योग्य है।आप इसे सदस्य चर या वैश्विक के रूप में उपयोग नहीं कर सकते हैं, और आप इसे तर्क या वापसी मान के रूप में पास नहीं कर सकते हैं। जब यह गुंजाइश छोड़ देता है तो स्मृति अनपिन होती है।

तो अगर स्मृति को केवल CoCreateInstance() को कॉल के दौरान वैध होने की आवश्यकता है तो पिन_प्टर जाने का तरीका है। आप स्मृति की एक प्रति लेने के लिए और पारित करने के लिए होगा तो नहीं है कि पर CoCreateInstance()

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