C ++的boost :: python包装对象的析构函数调用 [英] C++ destructor calling of boost::python wrapped objects

查看:140
本文介绍了C ++的boost :: python包装对象的析构函数调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当a的C ++析构函数执行boost :: python时,可以提供任何保证 考虑到零的时刻被称为包装的对象 对应的python对象的引用计数?

Does boost::python provide any guarantee when the C++ destructor of a wrapped object is called considering the moment of reaching the zero reference count of the corresponding python object?

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

I am concerned about a C++ object that opens a file for writing and performs the file closing in its destructor. Is it guaranteed that the file is written when all python references to the object are deleted or out of scope?

我的意思是:

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

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

My experience suggests that the destructor is always called at this point but could not find any guarantee for this.

推荐答案

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

Boost.Python makes the guarantee that if the Python object has ownership of the wrapped C++ object, then when the Python object is deleted, the wrapped C++ object will be deleted. The Python object's lifetime is dictated by Python, wherein when an object’s reference count reaches zero, the object may be immediately destroyed. For non-simplistic cases, such as cyclic references, the objects will be managed by the garbage collector, and may be destroyed before the program exits.

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

One Pythonic solution may be to expose a type that implements the context manager protocol. The content manager protocol is made up of a pair of methods: one which will be invoked when entering a runtime context, and one which will be invoked when exiting a runtime context. By using a context manager, one could control the scope in which a file is open.

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


下面是一个示例演示将RAII类型的类作为上下文公开给Python经理:


Here is an example demonstrating exposing a RAII-type class to Python as a context manager:

#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()

这篇关于C ++的boost :: python包装对象的析构函数调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆