#pragma once #include #include #include namespace c10 { // This is an safe owning holder for a PyObject, akin to pybind11's // py::object, with two major differences: // // - It is in c10/core; i.e., you can use this type in contexts where // you do not have a libpython dependency // // - It is multi-interpreter safe (ala torchdeploy); when you fetch // the underlying PyObject* you are required to specify what the current // interpreter context is and we will check that you match it. // // It is INVALID to store a reference to a Tensor object in this way; // you should just use TensorImpl directly in that case! struct C10_API SafePyObject { // Steals a reference to data SafePyObject(PyObject* data, c10::impl::PyInterpreter* pyinterpreter) : data_(data), pyinterpreter_(pyinterpreter) {} // In principle this could be copyable if we add an incref to PyInterpreter // but for now it's easier to just disallow it. SafePyObject(SafePyObject const&) = delete; SafePyObject& operator=(SafePyObject const&) = delete; ~SafePyObject() { pyinterpreter_->decref(data_, /*is_tensor*/ false); } c10::impl::PyInterpreter* pyinterpreter() const { return pyinterpreter_; } PyObject* ptr(const c10::impl::PyInterpreter*) const; private: PyObject* data_; c10::impl::PyInterpreter* pyinterpreter_; }; } // namespace c10