没有调用PyBind11析构函数?

时间:2019-04-01 10:16:36

标签: python c++ destructor pybind11

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

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

请有人解释这里有什么问题以及如何在destructor对象被垃圾回收时自动调用Python吗?

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

1 个答案:

答案 0 :(得分:0)

正如评论中提到的,这种行为的直接原因是 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)