我应该如何释放在类型映射中为结构的argout数组分配的内存?

2024-04-20 03:41:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用SWIG为Python包装一个C库。其中一个C方法需要 指向结构缓冲区和要填充和填充的元素数的指针 指向结构。对于pythonapi,我只想提供 元素的个数和返回值作为填充结构的元组。在

  C     : int fill_widgets(widget_t *buffer, int num_widgets);
  Python: fill_widgets(num_widgets) -> (widget, widget,...)

我已经写了一些类型映射,它们可以按我的需要工作——类型映射分配 一个基于Python输入参数的缓冲区,将缓冲区传递给C方法, 将其转换为Python元组,然后返回widgets的tuple。但我想不通 如果/何时/如何释放在我的类型映射中分配的内存。在

我最初包含了一个freearg类型映射来释放包装器时的缓冲区 函数退出,但我相信返回到Python的结构仍然使用 物理内存(即内存没有被复制,我只得到一个代理指针 使用相同的缓冲区)。我还试着设置SWIG_POINTER_OWN标志 当创建代理对象时(通过SWIGüNewPointerObj),但是由于我正在创建 指向缓冲区中每个元素的代理指针释放它们是没有意义的 全部。在这两种情况下,Python最终都会在以后的 free()调用。在

所以在创建代理时,如果不在typemap中使用freearg或SWIG_POINTER_OWN, 当结构的Python元组超出范围时,如何释放内存?在

下面是一个简单的SWIG接口,它展示了我所拥有的:

^{pr2}$

以及要构建/运行的示例:

$ swig -python test.i
$ gcc -I/path/to/python2.7 -shared -lpython2.7 test_wrap.c  -o _test.so
$ python
>>> import test
>>> _,widgets = test.fill_widgets(4)
>>> for w in widgets: print w.a, w.b
... 
0 0
1 2
2 4
3 6
>>> 

C中fill_小部件的用法示例:

int main()
{
    widget_t widgets[10];  // or widget_t *widgets = calloc(10, sizeof(widget_t))
    fill_widgets(widgets, 10);
}

Tags: 内存test元素类型代理widgetswidget结构
1条回答
网友
1楼 · 发布于 2024-04-20 03:41:54

有趣的是,您有1个缓冲区,但是创建了N个Python代理对象,所有这些对象都位于这个缓冲区中。在

假设您不愿意接受从缓冲区复制对象,那么您就得到了1:1的Python代理对象映射分配,然后处理原始缓冲区,我们基本上只有一个解决方案。这里的目的是确保每个Python对象也包含对拥有内存的对象的引用。只有在记忆中,我们才有可能把它放在高处,这样就没人能确定了。在

最简单的解决方案是为缓冲区中的第一个对象设置SWIG_POINTER_OWN(即指针真正引用从calloc返回的内存的对象),然后让其他每个代理对象不拥有内存,但保留对该对象的引用。在

为了实现这一点,我们对argout类型映射做了两个更改。首先,我们只为元组的第一个元素设置SWIG_POINTER_OWN。其次,我们调用PyObject_SetAttrString,只为第一个项目保留引用。结果是这样的:

%typemap (argout) (BUF, NUM){
    PyObject *tpl = PyTuple_New($2);
    for ($2_ltype i=0; i<$2; i++)
    {
        PyObject *item = SWIG_NewPointerObj(&$1[i], $1_descriptor, 0==i?SWIG_POINTER_OWN:0);
        if (i) {
            PyObject_SetAttrString(item,"_buffer",PyTuple_GET_ITEM(tpl, 0));
        } 
        PyTuple_SET_ITEM(tpl, i, item);
    }
    $result = SWIG_Python_AppendOutput($result, tpl);
}

我们可以交互检查参考计数是否如预期:

^{pr2}$

相关问题 更多 >