Mantid
Loading...
Searching...
No Matches
PythonObjectInstantiator.h
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2011 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7#pragma once
8
9//-----------------------------------------------------------------------------
10// Includes
11//-----------------------------------------------------------------------------
14
15#include <boost/python/extract.hpp>
16#include <boost/python/object.hpp>
17// older versions of boost::python seem to require this last, after the object
18// include
19#include <memory>
20
21namespace Mantid {
22namespace PythonInterface {
28 GILSharedPtrDeleter(const boost::python::converter::shared_ptr_deleter &deleter)
29 : m_deleter(boost::python::converter::shared_ptr_deleter(deleter.owner)) {}
34 void operator()(void const *data) {
36 m_deleter(data);
37 }
39 boost::python::converter::shared_ptr_deleter m_deleter;
40};
41
46template <typename Base> class PythonObjectInstantiator : public Kernel::AbstractInstantiator<Base> {
47public:
49 PythonObjectInstantiator(const boost::python::object &classObject) : m_classObject(classObject) {}
50
52 std::shared_ptr<Base> createInstance() const override;
53
55 Base *createUnwrappedInstance() const override;
56
57private:
59 boost::python::object m_classObject;
60};
61
66template <typename Base> std::shared_ptr<Base> PythonObjectInstantiator<Base>::createInstance() const {
67 using namespace boost::python;
69
70 object instance = m_classObject();
71 // The instantiator assumes that the exported type uses a
72 // HeldType=std::shared_ptr<Adapter>,
73 // where Adapter inherits from Base,
74 // see
75 // http://www.boost.org/doc/libs/1_42_0/libs/python/doc/v2/class.html#class_-spec.
76 // The advantage is that the memory management is very simple as it is all
77 // handled within the
78 // boost layer.
79
80 // Swap the deleter for one that acquires the GIL before actually deallocating
81 // the
82 // Python object or we get a segfault when deleting the objects on later
83 // versions of Python 2.7
84 auto instancePtr = extract<std::shared_ptr<Base>>(instance)();
85 auto *deleter = std::get_deleter<converter::shared_ptr_deleter, Base>(instancePtr);
86 instancePtr.reset(instancePtr.get(), GILSharedPtrDeleter(*deleter));
87 return instancePtr;
88}
89
94template <typename Base> Base *PythonObjectInstantiator<Base>::createUnwrappedInstance() const {
95 throw std::runtime_error("Unable to create unwrapped instance of Python object");
96}
97} // namespace PythonInterface
98} // namespace Mantid
The base class for instantiators.
Definition: Instantiator.h:25
Defines a structure for acquiring/releasing the Python GIL using the RAII pattern.
Base * createUnwrappedInstance() const override
Creates an instance of the object as raw pointer to the Base type.
std::shared_ptr< Base > createInstance() const override
Creates an instance of the object as shared_ptr to the Base type.
PythonObjectInstantiator(const boost::python::object &classObject)
Constructor taking a Python class object wrapped as a boost::python:object.
boost::python::object m_classObject
The class name.
Helper class which provides the Collimation Length for SANS instruments.
Definition: NDArray.h:49
Special shared_ptr::deleter object that locks the GIL while deleting the underlying Python object.
GILSharedPtrDeleter(const boost::python::converter::shared_ptr_deleter &deleter)
boost::python::converter::shared_ptr_deleter m_deleter
Main deleter object.
void operator()(void const *data)
Called when the shared_ptr reference count is zero.