C++析构函数调用 boost::p ython 包装的对象
C++ destructor calling of boost::python wrapped objects
boost::p ython是否提供任何保证,C++当一个考虑达到零的时刻,将包裹对象称为相应 Python 对象的引用计数?
我担心一个C++对象打开文件进行写入并在其析构函数中执行文件关闭。当对对象的所有 python 引用被删除或超出范围时,是否保证写入文件?
我的意思是:
A=MyBoostPythonObject()
del A # Is the C++ destructor of MyBoostPythonObject called here?
我的经验表明,此时总是调用析构函数,但找不到任何保证。
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()
相关文章:
- 包装一个对象并假装它是一个 int
- 错误:"释放后使用包装器对象 (WRAPPER_ESCAPE)"
- C++包装库:在堆栈上分配C++ C 中的对象
- 将对象传递给函数而不将其包装到 std::ref 中,而参数被指定为 const 引用
- 如何包装对象,使它们成为无法交互的单独类型?
- 为什么包装对象的大小低于预期
- 用SWIG包装对象从C++调用Python函数的最干净方法是什么
- 如何使用智能指针调用包装对象的方法
- 如何在 NodeJs 原生插件中使用 std::map 的未包装C++对象
- 如何通过unique_ptr调用包装对象的方法
- 用于包装C++对象的最佳 JNI 模式
- 用另一种语言包装C++对象的策略——内存管理
- 运行时故障类包装C对象
- 如何访问nodejs插件中的包装对象属性
- 如何在Cython中从另一个包装对象返回包装的c++对象
- 通过包装对象上的函数指针调用类方法出错
- SWIG不接受指针参数的包装对象
- 在Node.js和v8中调用一个使用包装对象作为参数的函数
- 包装C++对象以用于C#PInvoke时的析构函数执行
- 如何用boost包装c++对象.这样Python就不会自动调用它的析构函数