如何删除使用SWIG生成的Python包装器中的堆积对象?

时间:2013-03-03 10:41:25

标签: c++ python swig

我正在开发一个Python模块和一个C ++库。在C ++代码中,我有一个函数,它返回一个堆积的对象,如下所示。

MyClass* func()
{
  MyClass* myclass = new MyClass();
  return myclass;
}

但是当我在Python端使用这个函数时,我无法删除返回的对象。

myclass = func()
del myclass # still remains in memory

有人能告诉我如何在Python代码中删除返回的对象吗?

我可以将返回值的类型从MyClass *更改为MyClass,以便我可以避免此内存泄漏。但是我不想触及C ++代码,因为C ++库已经在另一个地方使用了。

1 个答案:

答案 0 :(得分:7)

请参阅SWIG文档11.2部分中的%newobject%typemap(newfree)指令。

引自文档:

  

某些应用程序中的常见问题是管理对象的正确所有权。例如,考虑这样的函数:

Foo *blah() {
   Foo *f = new Foo();
   return f;
}
  

如果包装函数blah(),SWIG不知道返回值是新分配的对象。因此,生成的扩展模块可能会产生内存泄漏(SWIG是保守的,永远不会删除对象,除非它确实知道返回的对象是新创建的。)

     

要解决此问题,您可以使用%newobject指令为代码生成器提供额外提示。例如:

%newobject blah;
Foo *blah();
  

%newobject与%rename和%exception完全相同。换句话说,您可以像以前一样将它附加到类成员和参数化声明。例如:

%newobject ::blah();                   // Only applies to global blah
%newobject Object::blah(int,double);   // Only blah(int,double) in Object
%newobject *::copy;                    // Copy method in all classes
...
  

当提供%newobject时,许多语言模块将安排获取返回值的所有权。这允许值在不再使用时自动进行垃圾回收。但是,这完全取决于目标语言(语言模块也可以选择忽略%newobject指令)。

     

与%newobject密切相关的是一个特殊的typemap。 “newfree”类型映射可用于释放新分配的返回值。它仅适用于已应用%newobject的方法,通常用于清除字符串结果。例如:

%typemap(newfree) char * "free($1);";
...
%newobject strdup;
...
char *strdup(const char *s);
  

在这种情况下,函数的结果是目标语言中的字符串。由于此字符串是原始结果的副本,因此不再需要strdup()返回的数据。示例中的“newfree”类型映射只是释放了这个内存。