Line data Source code
1 : // SPDX-License-Identifier: BSD-3-Clause 2 : // Copyright (c) 2023 Scipp contributors (https://github.com/scipp) 3 : /// @file 4 : /// @author Simon Heybrock 5 : #include "py_object.h" 6 : 7 : namespace py = pybind11; 8 : 9 : namespace scipp::python { 10 : 11 40047 : PyObject::~PyObject() { 12 40047 : py::gil_scoped_acquire acquire; 13 40047 : m_object = py::object(); 14 40047 : } 15 : 16 116 : PyObject::PyObject(const py::object &object) { 17 116 : py::gil_scoped_acquire acquire; 18 116 : m_object = object; // NOLINT(cppcoreguidelines-prefer-member-initializer) 19 116 : } 20 : 21 23 : bool PyObject::operator==(const PyObject &other) const { 22 : // Similar to above, re-acquiring GIL here due to segfault in Python C API 23 : // (PyObject_RichCompare). 24 23 : py::gil_scoped_acquire acquire; 25 46 : return to_pybind().equal(other.to_pybind()); 26 23 : } 27 : 28 25 : PyObject copy(const PyObject &obj) { 29 25 : const auto &object = obj.to_pybind(); 30 25 : if (object) { 31 : // It is essential to acquire the GIL here. Calling Python code otherwise 32 : // causes a segfault if the GIL has been released previously. Since this 33 : // copy operation is called by anything that copies variables, this includes 34 : // almost every C++ function with Python bindings because we typically do 35 : // release the GIL everywhere. 36 25 : py::gil_scoped_acquire acquire; 37 25 : py::module copy = py::module::import("copy"); 38 25 : py::object deepcopy = copy.attr("deepcopy"); 39 50 : return {deepcopy(object)}; 40 25 : } else { 41 0 : return {object}; 42 : } 43 : } 44 : 45 0 : std::ostream &operator<<(std::ostream &os, const PyObject &obj) { 46 0 : return os << to_string(obj); 47 : } 48 : 49 0 : std::string to_string(const PyObject &obj) { 50 0 : py::gil_scoped_acquire gil_{}; 51 0 : return py::str(obj.to_pybind()); 52 0 : } 53 : 54 : } // namespace scipp::python