4

我正在开发一个 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++ 库已经在其他地方使用。

4

1 回答 1

8

请参阅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 密切相关的是一个特殊的类型映射。“newfree”类型映射可用于释放新分配的返回值。它仅适用于已应用 %newobject 的方法,并且通常用于清理字符串结果。例如:

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

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

于 2013-03-03T15:02:22.867 回答