是否未调用PyBind11析构函数? [英] PyBind11 destructor not invoked?

查看:124
本文介绍了是否未调用PyBind11析构函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用PyBind11包装的c++类。问题是:当Python脚本结束时,c++destructor不会被自动调用。这会导致不整洁的退出,因为网络资源需要由析构函数释放。

作为一种解决办法,有必要显式删除Python对象,但我不明白为什么!

请解释一下这里出了什么问题,以及当Python对象被垃圾回收时如何自动调用destructor

Pybind11绑定代码:

py::class_<pcs::Listener>(m, "listener")
    .def(py::init<const py::object &, const std::string &, const std::string &, const std::string &, const std::string &, const std::set<std::string> &, const std::string & , const bool & , const bool & >(), R"pbdoc(
    Monitors network traffic.

    When a desired data source is detected a client instance is connected to consume the data stream.

    Reconstructs data on receipt, like a jigsaw.  Makes requests to fill any gaps.  Verifies the data as sequential.

    Data is output by callback to Python.  Using the method specified in the constructor, which must accept a string argument.
)pbdoc");

在Python中:

#Function to callback
def print_string(str):
    print("Python; " + str)

lstnr = listener(print_string, 'tcp://127.0.0.1:9001', clientCertPath, serverCertPath, proxyCertPath, desiredSources, 'time_series_data', enableCurve, enableVerbose)

#Run for a minute
cnt = 0
while cnt < 60:
    cnt += 1
    time.sleep(1)

#Need to call the destructor explicity for some reason    
del lstnr

推荐答案

正如评论中提到的,这种行为的直接原因是Python型垃圾回收器:当对象的引用计数器变为零时,垃圾回收器可能销毁该对象(从而调用C++析构函数),但它不一定要在那个时刻这样做。

这个想法在这里的回答中得到了更充分的阐述:

https://stackoverflow.com/a/38238013/790979

正如上面的链接中所提到的,如果您要在对象的生命周期结束时在Python中进行清理,那么context management是一个很好的解决方案,您可以在对象的包装器中定义__enter____exit__(无论是在pybind11中还是在Python本身中),让__exit__释放网络资源,然后在Python客户端代码中,类似于:


with listener(print_string, 'tcp://127.0.0.1:9001', clientCertPath, serverCertPath, proxyCertPath, desiredSources, 'time_series_data', enableCurve, enableVerbose) as lstnr:
    # Run for a minute
    cnt = 0
    while cnt < 60:
        cnt += 1
        time.sleep(1)

这篇关于是否未调用PyBind11析构函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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