C ++的boost :: python包装对象的析构函数调用

奥夫加

考虑到到达对应的python对象的零引用计数的时刻,boost :: python是否可以保证包装对象的C ++析构函数被调用时提供任何保证?

我担心一个C ++对象,该对象会打开一个文件进行写入并在其析构函数中执行文件关闭操作。是否可以保证在删除对该对象的所有python引用或超出范围时都写入文件?

我是说:

A=MyBoostPythonObject()
del A # Is the C++ destructor of MyBoostPythonObject called here?

我的经验表明,析构函数总是在此时被调用,但是对此没有任何保证。

坦纳·桑斯伯里(Tanner Sansbury)

Boost.Python保证,如果Python对象拥有包装的C ++对象的所有权,那么当删除Python对象时,包装的C ++对象将被删除。Python对象的生存期由Python决定,其中,当对象的引用计数达到零时,该对象可能会立即被销毁。对于非简单情况,例如循环引用,这些对象将由垃圾回收器管理,并可能在程序退出之前被销毁。

一个Pythonic解决方案可能是公开一种实现上下文管理器协议的类型内容管理器协议由一对方法组成:一种方法将在进入运行时上下文时被调用,而另一种方法将在退出运行时上下文时被调用。通过使用上下文管理器,可以控制打开文件的范围。

>>> with MyBoostPythonObject() as A:  # opens file.
...     A.write(...)                  # file remains open while in scope.
...                                   # A destroyed once context's scope is exited.

这是一个示例,该示例演示将RAII类型的类作为上下文管理器暴露给Python:

#include <boost/python.hpp>
#include <iostream>

// Legacy API.
struct spam
{
  spam(int x)    { std::cout << "spam(): " << x << std::endl;   }
  ~spam()        { std::cout << "~spam()" << std::endl;         }
  void perform() { std::cout << "spam::perform()" << std::endl; }
};

/// @brief Python Context Manager for the Spam class.
class spam_context_manager
{
public:

  spam_context_manager(int x): x_(x) {}

  void perform() { return impl_->perform(); }

// context manager protocol
public:

  // Use a static member function to get a handle to the self Python
  // object.
  static boost::python::object enter(boost::python::object self)
  {
    namespace python = boost::python;
    spam_context_manager& myself =
      python::extract<spam_context_manager&>(self);

    // Construct the RAII object.
    myself.impl_ = std::make_shared<spam>(myself.x_);

    // Return this object, allowing caller to invoke other
    // methods exposed on this class.
    return self;
  }

  bool exit(boost::python::object type,
            boost::python::object value,
            boost::python::object traceback)
  {
    // Destroy the RAII object.
    impl_.reset();
    return false; // Do not suppress the exception.
  }
private:
  std::shared_ptr<spam> impl_;
  int x_;
};


BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::class_<spam_context_manager>("Spam", python::init<int>())
    .def("perform", &spam_context_manager::perform)
    .def("__enter__", &spam_context_manager::enter)
    .def("__exit__", &spam_context_manager::exit)
    ;
}

互动用法:

>>> import example
>>> with example.Spam(42) as spam:
...     spam.perform()
...
spam(): 42
spam::perform()
~spam()

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

无法从python C ++包装器访问析构函数

C ++:析构函数在对象范围之外被调用?

C ++:删除对象而不调用析构函数

C++ 析构函数调用了错误的对象?

新的boost :: thread导致对象析构函数的调用次数比预期的次数多?

与Boost odeint集成期间的析构函数调用

C ++中的析构函数直接调用

C ++如何自动调用析构函数?

C ++析构函数未调用

C ++意外的析构函数调用

析构函数在C ++中调用向量

从对象原因到此类的调用析构函数的c ++ std :: thread调用方法

什么时候在C ++中调用要调用的对象的析构函数?

为什么在调用luaL_error时未调用C ++对象析构函数?

未调用C ++析构函数/未删除对象-潜在的内存泄漏

C#,删除带有子线程的对象时,GC没有调用析构函数

C ++调用析构函数并不会真正从内存中删除对象

什么时候在堆中的对象上调用C ++析构函数?

C ++-析构函数何时调用已使用但未分配的对象?

C ++为什么在堆栈中构造完对象后立即调用析构函数?

ctypes 包装器,用于通过带有析构函数的 C++ 类的值对象返回的函数

C ++破坏顺序:在类析构函数之前调用字段析构函数

C ++。在析构函数中调用虚拟成员函数

c++ - 在赋值时调用析构函数

如何使虚拟析构函数在C ++中被调用?

强制Java调用我的C ++析构函数(JNI)

什么时候调用C ++析构函数?

在多级继承中调用析构函数(C ++)

为什么在构造时调用C ++类的析构函数?