Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python模块中atexit调用的对象清理和函数序列 我使用PosithPython将Python与C++ C++库集成。遗留库具有一些全局初始化,然后其中的类使用应用程序范围的数据。我需要确保在销毁所有包装的对象后调用遗留库的shutdown函数,我认为这可以通过使用atexit注册shutdown函数来实现。但是,我发现atexit调用shutdown函数后,包装的对象正在被清理,从而导致遗留库中出现多个SEGFULT_Python_C++_Boost Python_Atexit - Fatal编程技术网

Python模块中atexit调用的对象清理和函数序列 我使用PosithPython将Python与C++ C++库集成。遗留库具有一些全局初始化,然后其中的类使用应用程序范围的数据。我需要确保在销毁所有包装的对象后调用遗留库的shutdown函数,我认为这可以通过使用atexit注册shutdown函数来实现。但是,我发现atexit调用shutdown函数后,包装的对象正在被清理,从而导致遗留库中出现多个SEGFULT

Python模块中atexit调用的对象清理和函数序列 我使用PosithPython将Python与C++ C++库集成。遗留库具有一些全局初始化,然后其中的类使用应用程序范围的数据。我需要确保在销毁所有包装的对象后调用遗留库的shutdown函数,我认为这可以通过使用atexit注册shutdown函数来实现。但是,我发现atexit调用shutdown函数后,包装的对象正在被清理,从而导致遗留库中出现多个SEGFULT,python,c++,boost-python,atexit,Python,C++,Boost Python,Atexit,我可以通过在退出之前对包装的对象调用del来实现所需的行为,但希望将删除留给Python。我已经查看了中的红色警告框,我想知道我的理想世界是否遥不可及 在python模块中包装遗留代码时,有没有建议确保在清除所有对象后调用shutdown方法 一些重要的平台细节: Python 2.7.2 Visual Studio 2013 64位构建 最小代码: #include <iostream> #include <boost/python.hpp> using name

我可以通过在退出之前对包装的对象调用del来实现所需的行为,但希望将删除留给Python。我已经查看了中的红色警告框,我想知道我的理想世界是否遥不可及

在python模块中包装遗留代码时,有没有建议确保在清除所有对象后调用shutdown方法

一些重要的平台细节:

  • Python 2.7.2
  • Visual Studio 2013
  • 64位构建
最小代码:

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

using namespace std;

namespace legacy
{
    void initialize() { cout << "legacy::initialize" << endl; }
    void shutdown() { cout << "legacy::shutdown" << endl; }

    class Test
    {
    public:
        Test();
        virtual ~Test();
    };

    Test::Test() { }
    Test::~Test() { cout << "legacy::Test::~Test" << endl; }
}

BOOST_PYTHON_MODULE(legacy)
{
    using namespace boost::python;
    legacy::initialize();
    class_<legacy::Test>("Test");
    def("_finalize", &legacy::shutdown);
    object atexit = object(handle<>(PyImport_ImportModule("atexit")));
    object finalize = scope().attr("_finalize");
    atexit.attr("register")(finalize);
}
#包括
#包括
使用名称空间std;
命名空间遗产
{
void initialize(){cout test=legacy.test()
>>>^Z
传统::关闭
遗留::测试::~Test


简而言之,创建一个保护类型,该类型将在其构造函数和析构函数中初始化和关闭旧库,然后通过每个公开对象中的智能指针管理保护


有一些微妙的细节会使销毁过程变得困难:

  • 中对象和模块中对象的销毁顺序是随机的
  • 没有模块的终结。特别是,动态加载的扩展模块不会卸载
  • 只有在销毁所有使用旧API的对象后,才应关闭旧API。但是,对象本身可能彼此不知道
为此,Boost.Python对象需要协调何时初始化和关闭遗留API。这些对象还需要对使用遗留API的遗留对象拥有所有权。使用,可以将责任划分为几个类

可以使用(RAII)习惯用法初始化和关闭遗留AP。例如,使用以下
遗留api\u guard
,当构建
遗留api\u guard
对象时,它将初始化遗留api。当
遗留api\u guard
对象被破坏时,它将关闭遗留api

将初始化或关闭旧API的简短保护。 结构遗留\u api\u保护 { 旧版_api_guard(){legacy::initialize();} ~legacy_api_guard(){legacy::shutdown();} };
由于多个对象需要共享对何时初始化和关闭旧版API的管理,因此可以使用智能指针(如
std::shared_ptr
)来负责管理保护。以下示例延迟初始化和关闭旧版API:

//@brief遗留API的全局共享保护。
std::弱\u ptr遗留\u api\u保护\u;
///@brief获取(或创建)遗留API的防护。
std::shared_ptr get_api_guard()
{
自动共享=遗留_api_guard_uu.lock();
如果(!共享)
{
shared=std::make_shared();
遗留_api_guard_=共享;
}
收益共享;
}
最后,将嵌入Boost.Python对象的实际类型需要在创建遗留对象的实例之前获得遗留API保护的句柄。此外,在销毁时,遗留API保护应该在遗留对象销毁后释放。实现这一点的一种非侵入性方法是使用pr向Boost.Python公开旧类型时提供自定义。公开该类型时,需要抑制Boost.Python生成的默认初始值设定项,因为将使用自定义工厂函数来控制对象创建:

//@brief legacy_object_holder是一个智能指针,可以容纳
///旧类型和帮助确保旧API已初始化
///当这些对象处于活动状态时。此智能指针将保留
///对传统库和面向用户的Python透明。
模板
类遗留对象持有者
{
公众:
类型定义T元素_类型;
模板
遗留对象持有者(Args&…Args)
:legacy_-guard(::get_-api_-guard()),
ptr_(std::make_shared(std::forward)使用自定义HeldType以非侵入方式惰性地保护具有共享管理的资源:

#包括//std::cout,std::endl
#包括//标准::共享ptr,标准::弱ptr
#包括
///@无法更改的简短旧命名空间。
命名空间遗产{
void initialize(){std::cout