有趣的是,您有1个缓冲区,但创建了N个Python代理对象,所有这些对象都位于单个缓冲区中。
  
  
   假设您不愿意将对象从缓冲区中复制出来,那么您将以1:1的比例分配给Python代理对象映射,然后处理原始缓冲区,我们基本上有一个解决方案需要解决。这里的目的是确保每个Python对象也包含对拥有内存的对象的引用。这样我们可以保持引用计数高,并且只有在确定没有人可能仍然指向它时才释放内存。
  
  
   
    calloc
   
   )然后让其他代理对象不拥有内存,但保留对内存的引用。
  
  
   
    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);
}
  
   我们可以交互检查参考计数是否符合预期:
  
  In [1]: import test
In [2]: import sys
In [3]: a,b=test.fill_widgets(20)
In [4]: sys.getrefcount(b[0])
Out[4]: 21
In [5]: sys.getrefcount(b[1])
Out[5]: 2
In [6]: b[1]._buffer
Out[6]: <test.widget_t; proxy of <Swig Object of type 'widget_t *' at 0xb2118d10> >
In [7]: b[1]._buffer == b[0]
Out[7]: True
In [8]: x,y,z = b[0:3]
In [9]: del a
In [10]: del b
In [11]: sys.getrefcount(x)
Out[11]: 4
In [12]: sys.getrefcount(y)
Out[12]: 2
In [13]: sys.getrefcount(z)
Out[13]: 2
In [14]: del x
In [15]: sys.getrefcount(y._buffer)
Out[15]: 3