2011-07-20 4 views
5

निम्न कोड में, foo_new() को कॉल के साथ प्रकार foo का ऑब्जेक्ट बनाया गया है और ऑब्जेक्ट के बाहरी-पॉइंटर को वापस लौटा दिया गया है बाद में गणना ptr_foo पास करके किया जाता है। ऑब्जेक्ट को अंततः foo_free (foo * X) के लिए एक स्पष्ट कॉल से मुक्त किया जाता है। सभी computations libfoo द्वारा किया जाता है।आर। कैल() इंटरफ़ेस और EXTPTRSXP: बाहरी आवंटित ऑब्जेक्ट्स के साथ सुरक्षा/अप्रतिबंध को समझना

क्या तथ्य यह है कि ptr_foo बनाया गया था कि foo ऑब्जेक्ट के भीतर अन्य सभी गतिशील आवंटित फ़ील्ड स्वचालित रूप से संरक्षित हैं? या, क्या यह संभव है कि "बार" जैसे क्षेत्रों को कचरा कलेक्टर द्वारा हटा दिया जा सके?

SEXP foo_new (SEXP n) { 
    SEXP ptr_foo; 
    foo *X = (foo*) foo_new(1, sizeof(foo)); 
    //foo is protected from garbage collection 
    assert(X); 
    X->bar = (int*) foo_add_bar(INTEGER_VALUE(n)); 
    //Is bar protected from garbage collection? 
    assert(X->bar); 
    PROTECT(ptr_foo = R_MakeExternalPtr(X, install("extptr_foo"), R_NilValue)); 
    R_RegisterCFinalizerEx(ptr_foo, ptr_foo_finalize, 1); 
    UNPROTECT(1); 
    return (ptr_foo); 
} 

धन्यवाद,

आरटी

उत्तर

3

ऐसा लगता है कि आपकी foo ऑब्जेक्ट आपकी खुद की रचना है (नहीं और SEXP)। यदि ऐसा है, तो इसका आर से कोई लेना-देना नहीं है और कचरा नहीं है और इसलिए इसे संरक्षित नहीं किया जा सकता है। कोई भी इसे या उसके खेतों को नहीं देखेगा लेकिन आप।

आपके द्वारा डाली गई बार वस्तु भी आपकी खुद की रचना है, न कि आर ऑब्जेक्ट (एक एसईएक्सपी) मुझे लगता है। यदि यह एक SEXP है या SEXP के भीतर डेटा को इंगित करता है तो उस डेटा को संरक्षित करने की आवश्यकता है। एसईएक्सपी में डेटा की एक प्रति बनाने के लिए एक सुरक्षित/आसान तरीका होगा।

जब ptr_foo ऑब्जेक्ट का अब आर और कचरा एकत्र नहीं किया जाता है, तो आपके poo_foo_finalize फ़ंक्शन को आपके foo ऑब्जेक्ट (और बार भाग) को हटाने के लिए बुलाया जाएगा।

+0

धन्यवाद टॉमी। यही वह था जिसे मैं उम्मीद कर रहा था। जैसा कि आप इंगित करते हैं, आर और libfoo के बीच डेटा का सभी एक्सचेंज एसईएक्सपी को अंदर और बाहर कॉपी करके होता है। पुस्तकालय द्वारा आवंटित सभी वस्तुओं को foo_free() कॉल से मुक्त किया जाता है। – user151410

1

शुरुआत के लिए, आप आर वस्तुओं के लिए calloc() या malloc() उपयोग करने के लिए नहीं जा सकते, "लेखन आर एक्सटेंशन" मैनुअल उस पर बहुत स्पष्ट है।

दूसरा, प्रत्येक आवंटन को अपनी सुरक्षा मिल जाएगी।

तीसरा, बाहरी सूचक वस्तुएं कहीं और बनाई गई किसी चीज के आर प्रस्तुतियां हैं (एक कैनोलिक उदाहरण के लिए, आरओडीबीसी पैकेज और डीबी इंटरफ़ेस के कार्यान्वयन को देखें)। मुझे नहीं लगता कि आपको बाहरी पॉइंटर ऑब्जेक्ट्स को भीतर से बनाना है।

+0

धन्यवाद Dirk, मैंने अपना मूल कोड संपादित किया। मैंने उदाहरण को सरल रखने के लिए 'कॉलोक()' का उपयोग किया। 'Foo' और 'bar' से युक्त निर्माण, विनाश और गणना' libfoo' में कार्यों के लिए कॉल द्वारा की जाती है। RODBC पैकेज के सूचक के लिए धन्यवाद। – user151410

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