-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathPythonCallback.hpp
More file actions
78 lines (59 loc) · 1.44 KB
/
PythonCallback.hpp
File metadata and controls
78 lines (59 loc) · 1.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#pragma once
#include <Python.h>
// ===========
// Conversions
// ===========
namespace conversions {
// Convert C++ type to Python
inline PyObject* arg_to_python(double x)
{
return PyFloat_FromDouble(x);
}
// Convert Python type to C++
template < typename T >
struct return_from_python
{
T operator() (PyObject*);
};
template < >
struct return_from_python<double>
{
double operator() (PyObject* v) const
{
return PyFloat_AsDouble(v);
}
};
} // namespace conversions
// =================
// Signature Handler
// =================
namespace internal {
template <std::size_t N, char C, char... Cs>
struct signature : signature<N - 1, C, C, Cs...> {};
template <char C, char... Cs>
struct signature<0UL, C, Cs...> {
static constexpr char const str[] = {'(', Cs..., ')', '\0'};
};
template <char C, char... Cs>
constexpr char const signature<0UL, C, Cs...>::str[];
} // namespace internal
// ===============
// Function caller
// ===============
template < typename ReturnType, typename ... Args >
ReturnType call(PyObject* callable, Args ... args)
{
// Acquire GIL
PyGILState_STATE gil = PyGILState_Ensure();
// Call the function
PyObject* const result =
PyEval_CallFunction(
callable,
internal::signature<sizeof...(args), 'O'>::str,
conversions::arg_to_python(args)...
);
conversions::return_from_python<ReturnType> converter;
// Release GIL
PyGILState_Release(gil);
return converter(result);
}