Как сохранить py::objects живыми после module.reload()

После перезагрузки модуля my_module все его объекты удаляются, но я хочу удалить объекты из C++. Как запретить Python удалять объекты?

#include <iostream>
#include <pybind11/embed.h>
class Obj{ ~Obj(){std::cout << "deleted" << std::endl;} };

PYBIND11_EMBEDDED_MODULE(module_obj, m) {
  py::class_<Obj>(m,"Obj");
}

/*
#my_module.py
import module_obj
o = module_obj.Obj()
*/

py::scoped_interpreter intpr;
auto my_module = py::module::import("my_module")
auto* o = my_module.attr("o").cast<Obj*>()
my_module.reload() // now o is deleted, how to prevent it?

person some dev    schedule 08.09.2019    source источник


Ответы (1)


Вам нужно поддерживать количество ссылок на объект o выше нуля. Самый простой способ — сделать py::object на стороне C++ (или, что то же самое, создать объект на стороне python).

#include <iostream>
#include <pybind11/embed.h>

namespace py=pybind11;

class Obj {
public:
  ~Obj() {
    std::cout << "deleted" << std::endl;
  }
};

PYBIND11_EMBEDDED_MODULE(my_module, m) {
  py::class_<Obj>(m, "Cat")
      .def(py::init());
}

int main() {
  py::scoped_interpreter intpr;
  std::cout << "Loading... " << std::endl;
  auto my_module = py::module::import("my_module");
  std::cout << "Load complete. " << std::endl;

  py::object o = my_module.attr("Cat")(); // create new cat, automatically increases/decreases ref count 
  std::cout << "Reloading... " << std::endl;
  my_module.reload(); // now o is deleted, how to prevent it?
  std::cout << "Reload complete. " << std::endl;
}

выход:

Loading... 
Load complete. 
Reloading... 
Reload complete. 
deleted
person Sergei    schedule 09.09.2019