Destroying a PyCapsule object
<p>According to <a href="https://docs.python.org/3.4/c-api/capsule.html?highlight=capsule" rel="nofollow">documentation</a>, the third argument to <code>PyCapsule_New()</code> can specify a destructor, which I assume should be called when the capsule is destroyed.</p>

<pre><code>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", &amp;w, &amp;h))
        return NULL;

    lashMapSimpleInit(map, &amp;w, &amp;h);

    return Py_BuildValue("O", pymap);

} 
</code></pre>

<p>However, when I instantiate the object and delete it or exit from Python console, the destructor doesn't seem to be called:</p>

<pre><code>&gt;&gt;&gt; a = mapSimpleInit(10,20)
&gt;&gt;&gt; a
&lt;capsule object "MAP_C_API" at 0x7fcf4959f930&gt;
&gt;&gt;&gt; del(a)
&gt;&gt;&gt; a = mapSimpleInit(10,20)
&gt;&gt;&gt; a
&lt;capsule object "MAP_C_API" at 0x7fcf495186f0&gt;
&gt;&gt;&gt; quit()
lash@CANTANDO ~/programming/src/liblashgame $ 
</code></pre>

<p>My guess is that it has something to do with the <code>Py_BuildValue()</code> returning a new reference to the "capsule", which upon deletion doesn't affect the original. Anyway, how would I go about ensuring that the object is properly destroyed?</p>

<p>Using Python 3.4.3 [GCC 4.8.4] (on linux)</p>

<p><code>Py_BuildValue("O", thingy)</code> will just increment the refcount for <code>thingy</code> and return it â the docs say that it returns a ânew referenceâ but that is not quite true when you pass it an existing <code>PyObject*</code>. </p>

<p>If these functions of yours â the ones in your question, that is â are all defined in the same translation unit, the destructor function will likely have to be declared <code>static</code> (so its full signature would be <code>static void mapDestroy(PyObject* capsule);</code>) to ensure that the Python API can look up the functionsâ address properly when it comes time to call the destructor.</p>

<p>â¦ You donât have to use a <code>static</code> function, as long as the destructorâs address in memory is valid. For example, Iâve successfully used <a href="https://github.com/fish2000/libimread/blob/master/python/im/include/pycapsule.hpp#L18-L30" rel="nofollow">a C++ non-capturing lambda as a destructor</a>, as non-capturing C++ lambdas can be converted to function pointers; if you want to use another way of obtaining and handing off a function pointer for your capsule destructor that works better for you, by all means go for it.</p>

python c cpython