2010-10-14 14 views
5

हेलो,पायथन संदर्भ गणना और ctypes

मुझे पाइथन संदर्भ गणना को समझने में कुछ परेशानी है। मैं जो करना चाहता हूं वह cty+ मॉड्यूल का उपयोग कर C++ से पायथन तक एक टुपल लौटाता है।

सी ++:

PyObject* foo(...) 
{ 

    ... 
    return Py_BuildValue("(s, s)", value1, value2); 
} 

पायथन:

pointer = c_foo(...) # c_foo loaded with ctypes 
obj = cast(pointer, py_object).value 

मैं obj के रेफरी गिनती के बारे में निश्चित नहीं था, इसलिए मैं sys.getrefcount() की कोशिश की और 3 मिला है। मुझे लगता है कि यह 2 होना चाहिए (getrefcount फ़ंक्शंस स्वयं को एक रेफरी बनाता है)।

अब मैं C++ में वापसी से पहले Py_DECREF() नहीं बना सकता क्योंकि वस्तु हटा दी जाती है। क्या मैं अजगर में रेफरी गिनती कम कर सकता हूं?

संपादित रेफरी गिनती के लिए क्या होता है जब डाली समारोह कहा जाता है? मैं नीचे दिए गए दस्तावेज से वास्तव में निश्चित नहीं हूं। http://docs.python.org/library/ctypes.html#ctypes.cast

ctypes.cast (obj, प्रकार) इस समारोह डाली ऑपरेटर सी में यह जो obj रूप में एक ही स्मृति ब्लॉक के लिए अंक प्रकार का एक नया उदाहरण देता है के समान है। प्रकार एक सूचक प्रकार होना चाहिए, और obj एक ऑब्जेक्ट होना चाहिए जिसे पॉइंटर के रूप में व्याख्या किया जा सकता है।

उत्तर

4

आगे के शोध पर मुझे पता चला कि कोई फ़ंक्शन का रिटर्न प्रकार निर्दिष्ट कर सकता है। http://docs.python.org/library/ctypes.html#callback-functions इससे कास्ट अप्रचलित हो जाता है और रेफरी गिनती अब कोई समस्या नहीं है।

clib = ctypes.cdll.LoadLibrary('some.so') 
c_foo = clib.c_foo 
c_foo.restype = ctypes.py_object 

जैसा कि कोई अतिरिक्त उत्तर नहीं दिया गया था, मैं जवाब के रूप में अपना नया समाधान स्वीकार करता हूं।

4

आपका C++ कोड official C-API का उपयोग कर एक क्लासिक आवरण हो रहा है और यह थोड़ा ctypes के बाद से अजीब आमतौर पर (int, नाव, आदि ...) की तरह अजगर में क्लासिक ग प्रकार का उपयोग कर के लिए प्रयोग किया जाता है है।

मैं व्यक्तिगत रूप से सी-एपीआई "अकेला" (सीटीपी के बिना) का उपयोग करता हूं लेकिन मेरे व्यक्तिगत अनुभव पर, आपको इस मामले में संदर्भ काउंटर के बारे में चिंता करने की ज़रूरत नहीं है क्योंकि आप Py_BuildValue के साथ देशी पाइथन प्रकार लौट रहे हैं। जब कोई फ़ंक्शन ऑब्जेक्ट देता है, तो स्वामित्व लौटा हुआ ऑब्जेक्ट कॉलिंग फ़ंक्शन को दिया जाता है।

उदाहरण के लिए, आप एक नक्शे की एक आवरण बनाया है:

आप (क्योंकि यह शून्य संकेत स्वीकार करता है की तुलना में बेहतर Py_INCREF/Py_DECREF) केवल जब तुम वस्तु का स्वामित्व परिवर्तित करना चाहते हैं के बारे में Py_XINCREF/Py_XDECREF चिंता करने की ज़रूरत पायथन में (चलिए टाइप की गई वस्तु py_map को कॉल करते हैं)। तत्व सी ++ वर्ग फू के हैं और आपने उनके लिए एक अन्य पायथन रैपर बनाया है (चलिए इसे py_Foo कहते हैं)। यदि आप एक समारोह है कि [] ऑपरेटर लपेट बनाते हैं, तो आप अजगर में एक py_Foo वस्तु वापस जाने के लिए जा रहे हैं:

F = py_Map["key"] 

लेकिन जब से स्वामित्व बुला समारोह को दिया जाता है, तो आपको F हटाना नाशक कॉल करेंगे और सी ++ में मानचित्र में एक विघटित objet के लिए एक सूचक है!

समाधान [] के आवरण में C++ में लिखने के लिए है:

... 
PyObject* result; // My py_Foo object 
Py_XINCREF(result); // transfer the ownership 
return result; 
} 

आप अजगर में borrowed and owned reference की धारणा पर एक नज़र रखना चाहिए।उचित संदर्भ काउंटर को समझना आवश्यक है।

+0

लेकिन आप एक पायथन-सी मॉड्यूल सही बनाते हैं? मैं इसे छोड़ना चाहता था और ctypes के साथ आप बस 'ctypes.cdll.LoadLibrary ('some.so')' कर सकते हैं। तो वापसी प्रकार हैंडलिंग अलग है। Ctypes के साथ यह 'ctypes.py_object' है। फिर मैं कास्ट फ़ंक्शन का उपयोग करता हूं और मुझे यकीन नहीं है कि कैसे रेफरी गिनती सही तरीके से संभाली जाती है। मेरा संपादन देखें। – tauran

+0

हां वास्तव में, यह थोड़ा और जटिल हो सकता है ... मैंने कास्ट के कोड स्रोत को पढ़ने की कोशिश की() लेकिन मेरे पास निवेश करने के लिए पर्याप्त समय नहीं था। मैं एक नज़र डालने की कोशिश करूंगा जब मेरे पास पर्याप्त समय होगा और मेरा जवाब संपादित करें यदि मुझे कुछ ऐसा लगता है जो साबित करता है कि सीटीपीएस स्वामित्व लेता है (यदि यह मामला है, तो शायद आपको इन समस्याओं को खत्म करने के लिए सीधे एक पायथन-सी ऑब्जेक्ट बनाने पर विचार करना चाहिए यह काफी आसान है क्योंकि आप पहले से ही PyObject के साथ काम कर रहे हैं) – ThR37

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