【问题标题】:Destroying a PyCapsule object销毁 PyCapsule 对象
【发布时间】:2017-01-11 07:56:06
【问题描述】:

根据documentationPyCapsule_New() 的第三个参数可以指定一个析构函数,我假设应该在胶囊被销毁时调用它。

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);

} 

但是,当我实例化对象并删除它或从 Python 控制台退出时,似乎没有调用析构函数:

>>> 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()
lash@CANTANDO ~/programming/src/liblashgame $ 

我的猜测是它与 Py_BuildValue() 返回对“胶囊”的新引用有关,删除后不会影响原始引用。无论如何,我将如何确保对象被正确销毁?

使用 Python 3.4.3 [GCC 4.8.4](在 linux 上)

【问题讨论】:

    标签: python c cpython


    【解决方案1】:

    Py_BuildValue("O", thingy) 只会增加thingy 的引用计数并返回它——文档说它返回一个“新引用”,但是当你将现有的PyObject* 传递给它时,情况就不完全正确了。

    如果您的这些函数(即您的问题中的函数)都定义在同一个翻译单元中,则可能必须将析构函数声明为 static(因此其完整签名将是 static void mapDestroy(PyObject* capsule);)以确保 Python API 在调用析构函数时可以正确查找函数的地址。

    ... 你不必使用static 函数,只要析构函数在内存中的地址是有效的。例如,我成功使用了a C++ non-capturing lambda as a destructor,因为非捕获 C++ lambda 可以转换为函数指针;如果您想使用另一种方式为您的胶囊析构函数获取和传递对您更有效的函数指针,请务必使用它。

    【讨论】:

      【解决方案2】:

      上面的代码有一个引用泄漏:pymap = PyCapsule_New() 返回一个新对象(它的 refcount 是 1),但是 Py_BuildValue("O", pymap) 创建一个对同一个对象的新引用,它的 refcount 现在是 2。

      只需return pymap;

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-27
        • 2013-07-13
        相关资源
        最近更新 更多