2010-06-29 4 views
5

में शून्य से * ऑब्जेक्ट में रूपांतरण सी # प्रोजेक्ट में, मुझे संरचना में संदर्भ डालकर ऑब्जेक्ट पैरामीटर को पास करने की आवश्यकता है। अर्थात मैं एक संरचना एक डिस्पैचरसी #

struct SOMESTRUCT 
{ 
    public int lpObject; 
} 

कहाँ lpObject तरह

class SomeClass 
{ 
    private string foo; 
} 

और SOMESTRUCT संरचना विधि से विधि में भेजा जाता है अंत में मेरी कोड तक पहुंचने के लिए एक कस्टम वस्तु के लिए एक सूचक धारण करने के लिए पारित कर दिया है। मैं निष्पादन प्रवाह है और न ही अजीब SOMSTRUCT प्रणाली संशोधित नहीं कर सकते, तो मैं अनुमान लगाया एकमात्र समाधान इस तरह एक सूचक करने के लिए मेरे वस्तु कास्ट करने के लिए किया गया था:

var myObject = new SomeClass(); 
GCHandle GC = GCHandle.Alloc(myObject, GCHandleType.Pinned); 
int myRef = GC.AddrOfPinnedObject().ToInt32(); 
GC.Free(); 

SOMESTRUCT struct; 
struct.lpObject = myRef; 
someMethod(struct); 

हालांकि, मैं समझ नहीं कैसे myObject सदस्यों को पुनः प्राप्त करने lpObject क्षेत्रों से। कुछ ऐसा:

SomeClass myObject = CastPointerToObject(struct.myRef) as SomeClass; 

क्या ऐसा करने का कोई तरीका है, या यह असंभव है? ऑब्जेक्ट को संभालने के लिए मैं कचरा कलेक्टर कैसे बता सकता हूं? क्या मुझे एक नया कचरा-एकत्रित वस्तु बनाना चाहिए और डेटा फ़ील्ड को फ़ील्ड द्वारा कॉपी करना चाहिए?

TYIA,

+0

int के बजाय IntPtr का उपयोग करें ....तो यह 64 बिट के साथ-साथ –

उत्तर

4

नहीं नहीं नहींनहीं !!!

यह

struct SOMESTRUCT 
{ 
    public SomeClass object_ref; 
} 

एक struct में एक संदर्भ स्टोर करने के लिए सही तरीका है।

आपके द्वारा लिखे गए कोड और स्वीकृत उत्तर, 100% टूटा हुआ हैं।

GC.AddrOfPinnedObject(GCHandle) द्वारा लौटाया गया पता केवल मान्य है जबकि GCHandle बरकरार है। आपको GCHandle.Free पर कॉल नहीं करना चाहिए, और आपको GCHandle एकत्रित नहीं होने देना चाहिए। आपके कोड में, जब आप इसे संग्रहीत करते हैं तो पता पहले से ही व्यर्थ है।

लेकिन आपको संदर्भ प्रकार के चर का उपयोग करके, कचरा संग्रह के दौरान पॉइंटर को प्रबंधित करने का ध्यान रखना चाहिए। तो आपको हुप्स के माध्यम से कूदने की जरूरत नहीं है। किसी प्रबंधित ऑब्जेक्ट का पता लेने का एकमात्र कारण यह है कि जब वह किसी मौजूदा मूल DLL फ़ंक्शन को पास कर देता है जो पॉइंटर को लौटने के बाद सहेज लेगा। उदाहरण के लिए, ओपनजीएल बफर सरणी के साथ यह आवश्यक है। अन्य सी # विधियों को कॉल करते समय, यह आवश्यक नहीं है।

यदि SOMESTRUCT वास्तव में कुछ डीएलएल फ़ंक्शन द्वारा उपयोग किया जाने वाला मूल डेटा प्रकार है जिसका आपने उल्लेख नहीं किया है, तो आपको GCHandle जीवित रखना सुनिश्चित करना होगा। केवल GCHandle मौजूद होने तक ही आपके द्वारा प्राप्त पॉइंटर वैध रहेगा।

+0

सहमत हुए। स्वीकृत उत्तर सही नहीं है; हालांकि मुझे लगता है कि ऐसी कहानी के लिए और भी कुछ है जिसे हम नहीं जानते हैं, अन्यथा, रनटाइम सही तरीके से मार्शलिंग का प्रबंधन कब करेगा? – codekaizen

+0

@codekaizen: हां, आवश्यकता है कि "SOMESTRUCT प्रकार बदला नहीं जा सकता" में कुछ तर्क होना चाहिए जिसे हमें प्रोग्राम को सही तरीके से हल करने के लिए जानना आवश्यक है। –

+0

SOMESTRUCT प्रकार एक "कस्टम सूचक" के साथ एक विंडो संदेश संरचना है। इस सूचक का मूल रूप से उपयोग किया गया था (प्रोग्राम में) धारावाहिक वस्तुओं वाले तारों को संदर्भित करने के लिए, जो ठीक (तरह) ठीक काम करते थे। मेरे कोड में, कुछ वर्ग serializable नहीं थे इसलिए मुझे एक और समाधान के साथ आना पड़ा। वास्तव में, स्वीकार्य समाधान ठीक दिखता था लेकिन कभी परीक्षण नहीं किया गया था, क्योंकि इससे हल होने वाली और समस्याएं उत्पन्न हुईं; इसलिए मैंने अभी "पॉइंटर/सीरियलाइजेशन" चीज छोड़ दी और चीजों को करने का एक और सी # -श तरीका इस्तेमाल किया। – slaphappy

2

आप मतलब है कि आप वापस आ सूचक एक struct करने के लिए वापस कास्ट करने के लिए करना चाहते हैं?

इसी के लिए:

lvHitTestInfo = (LVHITTESTINFO)Marshal.PtrToStructure(lP, typeof(LVHITTESTINFO)); 

कहाँ lvHitTestInfo एक संरचना है और एक सूचक एल.पी.।

या मैं आपके प्रश्न को ठीक से समझ नहीं पाया। शायद आप अधिक (अधिक पूर्ण कोड नमूना) समझा सकते हैं।

+0

में काम करेगा हां और नहीं। मैं लौटे पॉइंटर को ऑब्जेक्ट में डालना चाहता हूं। मैं अपने प्रश्न में अधिक जानकारी जोड़ूंगा। – slaphappy

+0

मैंने नहीं देखा कि यह विधियां ऑब्जेक्ट्स के साथ भी काम करती हैं। यह वही है जिसे मैं देख रहा था। आपके सहयोग के लिए धन्यवाद ! – slaphappy

+0

मैं वहां कभी नहीं गया लेकिन यह जानना कि क्या यह संभव है कि आपको वास्तव में क्या लौटाया गया है इसका सटीक विवरण देना होगा। पॉइंटर इंगित करता है कि वास्तव में क्या करता है। देखें, अगर आप अप्रबंधित कोड से बातचीत कर रहे हैं तो यह बहुत ही असंभव है कि आप एक प्रबंधित ऑब्जेक्ट पर जा सकेंगे। यह जानने का कोई तरीका नहीं है कि कहां जाता है। – Jeroen