2016-09-03 14 views
5

documentation के अनुसार, PyCapsule_New() पर तीसरा तर्क एक विनाशक निर्दिष्ट कर सकता है, जिसे कैप्सूल नष्ट होने पर मुझे माना जाना चाहिए।एक PyCapsule ऑब्जेक्ट को नष्ट करना

void mapDestroy(PyObject *capsule) { 

    lash_map_simple_t *map; 
    fprintf(stderr, "Entered destructor\n"); 
    map = (lash_map_simple_t*)PyCapsule_GetPointer(capsule, "MAP_C_API"); 
    if (map == NULL) 
     return; 
    fprintf(stderr, "Destroying map %p\n", map); 
    lashMapSimpleFree(map); 
    free(map); 

} 

static PyObject * mapSimpleInit_func(PyObject *self, PyObject *args) { 

    unsigned int w; 
    unsigned int h; 
    PyObject *pymap; 

    lash_map_simple_t *map = (lash_map_simple_t*)malloc(sizeof(lash_map_simple_t)); 

    pymap = PyCapsule_New((void *)map, "MAP_C_API", mapDestroy); 

    if (!PyArg_ParseTuple(args, "II", &w, &h)) 
     return NULL; 

    lashMapSimpleInit(map, &w, &h); 

    return Py_BuildValue("O", pymap); 

} 

हालांकि, जब मैं वस्तु का दृष्टांत और यह या अजगर कंसोल से बाहर निकलने को हटाते हैं, नाशक के नाम से जाना प्रतीत नहीं होता:

>>> a = mapSimpleInit(10,20) 
>>> a 
<capsule object "MAP_C_API" at 0x7fcf4959f930> 
>>> del(a) 
>>> a = mapSimpleInit(10,20) 
>>> a 
<capsule object "MAP_C_API" at 0x7fcf495186f0> 
>>> quit() 
[email protected] ~/programming/src/liblashgame $ 

मेरा अनुमान है कि यह साथ क्या करने के लिए कुछ किया है Py_BuildValue() "कैप्सूल" के लिए एक नया संदर्भ लौटा रहा है, जो हटाने पर मूल को प्रभावित नहीं करता है। वैसे भी, मैं यह सुनिश्चित करने के लिए कैसे जाउंगा कि वस्तु ठीक से नष्ट हो गई है?

अजगर 3.4.3 [जीसीसी 4.8.4] (लिनक्स पर) का उपयोग करना

उत्तर

0

Py_BuildValue("O", thingy) सिर्फ thingy के लिए refcount को बढ़ा देते हैं और यह वापस आ जाएगी - डॉक्स का कहना है कि यह एक "नया संदर्भ" रिटर्न लेकिन वह नहीं है जब आप इसे मौजूदा PyObject* पास करते हैं तो काफी सच है।

यदि आपके इन कार्यों में से आपके - आपके प्रश्न में हैं, जो सभी एक ही अनुवाद इकाई में परिभाषित हैं, तो विनाशक समारोह को static घोषित करना होगा (इसलिए इसका पूरा हस्ताक्षर static void mapDestroy(PyObject* capsule); होगा) पाइथन एपीआई विनाशक को कॉल करने का समय आने पर कार्यों के पते को ठीक से देख सकता है।

... आपको static फ़ंक्शन का उपयोग करने की आवश्यकता नहीं है, जब तक स्मृति में विनाशक का पता मान्य है। उदाहरण के लिए, मैंने सफलतापूर्वक a C++ non-capturing lambda as a destructor का उपयोग किया है, क्योंकि गैर-कैप्चरिंग C++ लैम्बडास को फ़ंक्शन पॉइंटर्स में परिवर्तित किया जा सकता है; यदि आप अपने कैप्सूल विनाशक के लिए फ़ंक्शन पॉइंटर प्राप्त करने और उसे बंद करने का एक और तरीका उपयोग करना चाहते हैं जो आपके लिए बेहतर काम करता है, तो हर तरह से इसके लिए जाएं।

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