8

我正在尝试使用boost::shared_ptr's 来允许我在我的 python 脚本中使用 c++ 文件 I/O 流对象。但是,生成的包装器警告我它正在泄漏内存。

这是一个显示问题的最小.i文件:

%module ptrtest

%include "boost_shared_ptr.i"
%include "std_string.i"

%shared_ptr( std::ofstream )

%{
#include <fstream>
#include <boost/shared_ptr.hpp>

typedef boost::shared_ptr< std::ofstream > ofstream_ptr;

ofstream_ptr mk_out(const std::string& fname ){
    return ofstream_ptr( new std::ofstream( fname.c_str() ) );
}

%}

ofstream_ptr mk_out(const std::string& fname );


%pythoncode %{

def leak_memory():
    ''' demonstration function -- when I call
        this, I get a warning about memory leaks
    ''''
    ostr=mk_out('/tmp/dont_do_this.txt')


%}

这是警告:

In [2]: ptrtest.leak_memory()
swig/python detected a memory leak of type 'ofstream_ptr *', no destructor found.

有没有办法修改.i文件来告诉接口如何正确处理 shared_ptr ?

4

1 回答 1

9

您的示例缺少让析构函数运行的两个部分:

  1. 由于 SWIGstd::ofstream对默认行为一无所知,除了传递一个不透明的句柄之外什么都不做。有关此问题的进一步讨论,请参见我的另一个答案。

    此处的解决方法是在您的接口文件中提供一个空定义,std::ofstream以说服 SWIG 它知道足以做更多事情,即使您不打算公开任何成员。

  2. SWIG 需要查看 typedef 本身 - 在里面%{ %}它只是直接传递给输出模块,而不是在包装本身中使用。

因此,您的示例变为:

%module ptrtest

%include "boost_shared_ptr.i"
%include "std_string.i"

%shared_ptr( std::ofstream )

namespace std {
  class ofstream {
  };
}

%{
#include <fstream>
#include <boost/shared_ptr.hpp>

typedef boost::shared_ptr< std::ofstream > ofstream_ptr;

ofstream_ptr mk_out(const std::string& fname ){
    return ofstream_ptr( new std::ofstream( fname.c_str() ) );
}
%}

typedef boost::shared_ptr< std::ofstream > ofstream_ptr;
ofstream_ptr mk_out(const std::string& fname );

%pythoncode %{
def leak_memory():
    ostr=mk_out('/tmp/dont_do_this.txt')
%}

为了将来参考,您可以避免重复仅存在于 .i 文件中的内容%inline

%inline %{
typedef boost::shared_ptr< std::ofstream > ofstream_ptr;

ofstream_ptr mk_out(const std::string& fname ){
    return ofstream_ptr( new std::ofstream( fname.c_str() ) );
}
%}

它一次性声明、定义和包装它。

于 2013-09-19T20:25:57.830 回答