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

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

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

我已经编写了类型映射,让它按我想要的方式工作-类型映射根据Python输入参数分配缓冲区,将缓冲区传递给C方法,将其转换为Python元组,然后返回窗口小部件的元组。但我不知道是否/何时/如何释放我的类型映射中分配的内存。

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

那么,在创建代理时,如果不在类型映射或SWIG_POINTER_OWN中使用freearg,当Python tuple- of -structs超出作用域时,如何释放内存?

这是一个简单的SWIG界面,演示了我所拥有的:

%module "test"

%typemap (in, numinputs=1) (BUF, NUM){
    $2 = PyInt_AsLong($input);
    $1 = ($1_type)calloc($2, sizeof($*1_type));
}

%typemap (argout) (BUF, NUM){
    PyObject *tpl = PyTuple_New($2);
    for ($2_ltype i=0; i<$2; i++)
    {
        PyTuple_SET_ITEM(tpl, i, SWIG_NewPointerObj(&$1[i], $1_descriptor, 0));
    }
    $result = SWIG_Python_AppendOutput($result, tpl);
}

%typemap (freearg) (BUF, NUM){
    //free($1);
}

%apply (BUF, NUM) {(widget_t *buf, int num_widgets)};

%inline {
typedef struct {int a; int b;} widget_t;

int fill_widgets(widget_t *buf, int num_widgets)
{
    for(int i=0; i<num_widgets; i++)
    {
        buf[i].a = i;
        buf[i].b = 2*i;
    }
    return num_widgets;
}
}

下面是构建/运行的示例:

$ 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_widgets的用法示例:

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

转载请注明出处:http://www.intsu.net/article/20230519/1031960.html