Mantid
Loading...
Searching...
No Matches
StdFunctionExporter.h
Go to the documentation of this file.
2
3#include <boost/python.hpp>
4#include <boost/python/converter/registry.hpp>
5#include <functional>
6#include <string>
7#include <type_traits>
8
9namespace {
10
11// Wrap raw pointers as Python objects holding the C++ pointer; nullptr -> None.
12template <typename T> inline boost::python::object wrap_for_python(T *p) {
13 if (p)
14 return boost::python::object(boost::python::ptr(p));
15 return boost::python::object(); // None
16}
17
18// Pass non-pointer arguments through as regular Python objects (numbers, strings, etc.).
19template <typename T>
20inline typename std::enable_if<!std::is_pointer<typename std::decay<T>::type>::value, boost::python::object>::type
21wrap_for_python(T &&v) {
22 return boost::python::object(std::forward<T>(v));
23}
24
25} // namespace
26
27namespace Mantid {
28namespace PythonInterface {
29
30template <typename R, typename... Args> struct std_function_from_python {
32 boost::python::converter::registry::push_back(&convertible, &construct,
33 boost::python::type_id<std::function<R(Args...)>>());
34 }
35
36 static void *convertible(PyObject *obj_ptr) { return PyCallable_Check(obj_ptr) ? obj_ptr : nullptr; }
37
38 static void construct(PyObject *obj_ptr, boost::python::converter::rvalue_from_python_stage1_data *data) {
39 using func_t = std::function<R(Args...)>;
40 void *storage =
41 reinterpret_cast<boost::python::converter::rvalue_from_python_storage<func_t> *>(data)->storage.bytes;
42
43 boost::python::handle<> hnd(boost::python::borrowed(obj_ptr));
44 boost::python::object cb(hnd);
45
46 new (storage) func_t([cb](Args... args) -> R {
47 PyGILState_STATE gstate = PyGILState_Ensure();
48 try {
49 // Wrap each argument: pointers -> boost::python::ptr, scalars -> as-is.
50 boost::python::object res = cb(wrap_for_python(std::forward<Args>(args))...);
51 R out = boost::python::extract<R>(res);
52 PyGILState_Release(gstate);
53 return out;
54 } catch (boost::python::error_already_set &) {
55 PyGILState_Release(gstate);
56 throw PythonException();
57 }
58 });
59
60 data->convertible = storage;
61 }
62};
63
64} // namespace PythonInterface
65} // namespace Mantid
double value
The value of the point.
Definition FitMW.cpp:51
Exception type that captures the current Python error state as a generic C++ exception for any genera...
Helper class which provides the Collimation Length for SANS instruments.
static void construct(PyObject *obj_ptr, boost::python::converter::rvalue_from_python_stage1_data *data)