2009-10-15 10 views
10

मैं C++ कक्षाओं से पाइथन मॉड्यूल बनाने के लिए बूस्ट.पथन का उपयोग कर रहा हूं। और मैं संदर्भों के साथ एक समस्या में भाग गया।Boost.Python - संदर्भ द्वारा वापस कैसे करें?

निम्नलिखित मामले पर कंडिडर जहां मेरे पास अधिभारित विधियों के साथ कक्षा फू है जो या तो मूल्य या संदर्भ द्वारा वापस आ सकता है।

यह निर्दिष्ट करना कि एक हस्ताक्षर टाइप करने के बाद मूल्य द्वारा वापसी का उपयोग करना आसान था। लेकिन मुझे लगता है कि यह return_value_policy का उपयोग करके एक संदर्भ भी संभव हो सकता है। हालांकि, उचित लग रहा था (doc) का उपयोग करना; return_value_policy<reference_existing_object> काम नहीं कर रहा था।

क्या मैंने गलत समझा है कि यह क्या करता है?

struct Foo { 
    Foo(float x) { _x = x; } 
    float& get() { return _x; } 
    float get() const { return _x; } 
private: 
    float _x; 
}; 

// Wrapper code 
BOOST_PYTHON_MODULE(my_module) 
{ 
    using namespace boost::python; 
    typedef float (Foo::*get_by_value)() const; 
    typedef float& (Foo::*get_by_ref)(); 

    class_<Foo>("Foo", init<float>()) 
     .def("get", get_by_value(&Foo::get)) 
     .def("get_ref", get_by_ref(&Foo::get), 
      return_value_policy<reference_existing_object>())//Doesn't work 
     ; 
} 

नोट: मुझे पता है कि जीवन के प्रबंधन के बिना मौजूदा वस्तु को संदर्भित करना खतरनाक हो सकता है।

अद्यतन:
ऐसा लगता है कि यह वस्तुओं के लिए काम करता है नहीं लेकिन बुनियादी डेटा प्रकार।
इस संशोधित उदाहरण लें:

struct Foo { 
    Foo(float x) { _x = x; } 
    float& get() { return _x; } 
    float get() const { return _x; } 
    void set(float f){ _x = f;} 
    Foo& self(){return *this;} 
private: 
    float _x; 
}; 

// Wrapper code 
using namespace boost::python; 
BOOST_PYTHON_MODULE(my_module) 
{ 
    typedef float (Foo::*get_by_value)() const; 

    class_<Foo>("Foo", init<float>()) 
     .def("get", get_by_value(&Foo::get)) 
     .def("get_self", &Foo::self, 
      return_value_policy<reference_existing_object>()) 
     .def("set", &Foo::set); 
     ; 
} 

जो एक परीक्षा में अपेक्षित परिणाम दिया:

>>> foo1 = Foo(123) 
>>> foo1.get() 
123.0 
>>> foo2 = foo1.get_self() 
>>> foo2.set(1) 
>>> foo1.get() 
1.0 
>>> id(foo1) == id(foo2) 
False 

उत्तर

7

अजगर में, वहाँ अपरिवर्तनीय प्रकार की अवधारणा है। एक अपरिवर्तनीय प्रकार का मूल्य बदल नहीं सकता है। अंतर्निहित अपरिवर्तनीय प्रकार के उदाहरण int, float और str हैं।

ऐसा कहकर, आप boost::python के साथ जो भी चाहते हैं वह नहीं कर सकते हैं, क्योंकि पाइथन स्वयं आपको फ़ंक्शन द्वारा लौटाए गए फ्लोट के मान को बदलने की अनुमति नहीं देता है।

आपका दूसरे उदाहरण एक ही समाधान से पता चलता है, एक और पतली रैपर बनाने के लिए हो सकता है और है कि उजागर होगा:

void Foo_set_x(Foo& self, float value) { 
    self.get() = value; 
} 

class_<Foo>("Foo", init<float>()) 
    ... 
    .def("set", &Foo_set_x); 
; 

कौन सा ++ वर्ग मूल सी बदलने के लिए की तुलना में एक बेहतर समाधान है।

0

मैं Boost.Python के बारे में ज्यादा पता नहीं है, इसलिए मैं सवाल है, गलत हो सकता है, जिसमें मामला यह पूरी तरह से अनुपयोगी है। लेकिन यहां जाता है:

पायथन में आप संदर्भ या मूल्य से लौटने के बीच चयन नहीं कर सकते हैं, भेद पाइथन में समझ में नहीं आता है। मुझे इसके बारे में सोचना सबसे आसान लगता है क्योंकि सब कुछ संदर्भ द्वारा संभाला जा रहा है।

आपके पास केवल ऑब्जेक्ट हैं, और आपके पास उन ऑब्जेक्ट्स के नाम हैं। तो

foo = "ryiuy" 

स्ट्रिंग वस्तु "ryiuy" बनाता है और फिर आप नाम "foo" के साथ कि स्ट्रिंग वस्तु का उल्लेख कर सकते हैं। तो पायथन में, जब आप कुछ पारित करते हैं, तो आप उस वस्तु को पारित कर देते हैं। इस तरह के "मूल्य" नहीं हैं, इसलिए आप मान पास नहीं कर सकते हैं। लेकिन फिर, यह एक वैध दृष्टिकोण भी है कि संदर्भ या तो वस्तुएं और उनके नाम संदर्भ नहीं हैं।

तो जवाब है, मुझे लगता है कि, जब आप सी में संदर्भ प्राप्त करते हैं, तो आपको उस ऑब्जेक्ट का संदर्भ पारित करने की आवश्यकता होती है जो पाइथन में संदर्भ संदर्भ देता है। और जब आपको सी में कोई मान मिलता है, तो आपको उस मान से संदर्भित करने की आवश्यकता होती है जिसे आप उस मान से पाइथन में बनाते हैं।

+0

हाँ, मुझे पता है कि पाइथन में सबकुछ संदर्भ है। जब मैं Boost.Python के साथ एक पायथन विधि बनाता हूं जो "मूल्य से" लौटाता है, तो वह उस प्रकार की एक प्रति देता है। मैं क्या करना चाहता हूं * प्रति * प्रतिलिपि नहीं है, बल्कि इसके बजाय एक ही उदाहरण का संदर्भ बनाएं। – mandrake

0

क्या आप सुनिश्चित हैं कि सी ++ ऑब्जेक्ट की प्रतिलिपि बनाई जा रही है? आपको प्रत्येक बार एक नया पायथन ऑब्जेक्ट मिलेगा, लेकिन एक ही सी ++ ऑब्जेक्ट का संदर्भ देता है। आप कैसे निर्धारित कर रहे हैं कि ऑब्जेक्ट की प्रतिलिपि बनाई गई है?

+0

जब मैं संदर्भों का उपयोग करने का प्रयास करता हूं तो यह संकलित नहीं होता है। यह निर्धारित करने के लिए कि क्या इसका संदर्भ या प्रतियां आसान है। जो भी आप सोचते हैं उसके लिए दो संदर्भ बनाएं, एक को संशोधित करें और देखें कि परिवर्तन दूसरे में दिखाई देते हैं या नहीं। (आईडी (ओबीजे) का उपयोग कर काम नहीं करेगा)। – mandrake

+0

हाँ, यह जांचने के लिए कहा गया था कि आप आईडी() का उपयोग नहीं कर रहे थे। संकलन त्रुटि क्या है? – Ben

+0

यह एक बढ़ावा है :: STATIC_ASSERTION_FAILURE, जो इंगित करता है कि जो कुछ मैं करता हूं वह असमर्थित या अवैध है। मैं बस नहीं जानता कि क्या। – mandrake

2

मुझे लगता है कि आप इसके बजाय return internal reference चाहते हैं। मैंने ऐसा कुछ करने के लिए पहले इस्तेमाल किया है।

संपादित करें: Latest doc

+0

यह वही सौदा है। यह वस्तुओं पर काम करता है लेकिन मूल डेटा प्रकार नहीं। – mandrake

+0

दस्तावेज़ीकरण का लिंक संस्करण 1.38 के लिए है, जो इस टिप्पणी के रूप में बहुत पुराना है (1.61 वर्तमान है) – ofloveandhate

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