μHAL (v2.8.17)
Part of the IPbus software repository
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
functional.h
Go to the documentation of this file.
1/*
2 pybind11/functional.h: std::function<> support
3
4 Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
6 All rights reserved. Use of this source code is governed by a
7 BSD-style license that can be found in the LICENSE file.
8*/
9
10#pragma once
11
12#include "pybind11.h"
13
14#include <functional>
15
18
19template <typename Return, typename... Args>
20struct type_caster<std::function<Return(Args...)>> {
21 using type = std::function<Return(Args...)>;
23 using function_type = Return (*)(Args...);
24
25public:
26 bool load(handle src, bool convert) {
27 if (src.is_none()) {
28 // Defer accepting None to other overloads (if we aren't in convert mode):
29 if (!convert) {
30 return false;
31 }
32 return true;
33 }
34
35 if (!isinstance<function>(src)) {
36 return false;
37 }
38
39 auto func = reinterpret_borrow<function>(src);
40
41 /*
42 When passing a C++ function as an argument to another C++
43 function via Python, every function call would normally involve
44 a full C++ -> Python -> C++ roundtrip, which can be prohibitive.
45 Here, we try to at least detect the case where the function is
46 stateless (i.e. function pointer or lambda function without
47 captured variables), in which case the roundtrip can be avoided.
48 */
49 if (auto cfunc = func.cpp_function()) {
50 auto *cfunc_self = PyCFunction_GET_SELF(cfunc.ptr());
51 if (isinstance<capsule>(cfunc_self)) {
52 auto c = reinterpret_borrow<capsule>(cfunc_self);
53 auto *rec = (function_record *) c;
54
55 while (rec != nullptr) {
56 if (rec->is_stateless
57 && same_type(typeid(function_type),
58 *reinterpret_cast<const std::type_info *>(rec->data[1]))) {
59 struct capture {
61 };
62 value = ((capture *) &rec->data)->f;
63 return true;
64 }
65 rec = rec->next;
66 }
67 }
68 // PYPY segfaults here when passing builtin function like sum.
69 // Raising an fail exception here works to prevent the segfault, but only on gcc.
70 // See PR #1413 for full details
71 }
72
73 // ensure GIL is held during functor destruction
74 struct func_handle {
75 function f;
76#if !(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17))
77 // This triggers a syntax error under very special conditions (very weird indeed).
78 explicit
79#endif
80 func_handle(function &&f_) noexcept
81 : f(std::move(f_)) {
82 }
83 func_handle(const func_handle &f_) { operator=(f_); }
84 func_handle &operator=(const func_handle &f_) {
86 f = f_.f;
87 return *this;
88 }
89 ~func_handle() {
91 function kill_f(std::move(f));
92 }
93 };
94
95 // to emulate 'move initialization capture' in C++11
96 struct func_wrapper {
97 func_handle hfunc;
98 explicit func_wrapper(func_handle &&hf) noexcept : hfunc(std::move(hf)) {}
99 Return operator()(Args... args) const {
101 object retval(hfunc.f(std::forward<Args>(args)...));
102 /* Visual studio 2015 parser issue: need parentheses around this expression */
103 return (retval.template cast<Return>());
104 }
105 };
106
107 value = func_wrapper(func_handle(std::move(func)));
108 return true;
109 }
110
111 template <typename Func>
112 static handle cast(Func &&f_, return_value_policy policy, handle /* parent */) {
113 if (!f_) {
114 return none().inc_ref();
115 }
116
117 auto result = f_.template target<function_type>();
118 if (result) {
119 return cpp_function(*result, policy).release();
120 }
121 return cpp_function(std::forward<Func>(f_), policy).release();
122 }
123
125 const_name("Callable[[") + concat(make_caster<Args>::name...)
127 + const_name("]"));
128};
129
Definition: pytypes.h:1776
Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object.
Definition: pybind11.h:81
\rst Holds a reference to a Python object (no reference counting)
Definition: pytypes.h:194
const handle & inc_ref() const &
\rst Manually increase the reference count of the Python object.
Definition: pytypes.h:211
Definition: pytypes.h:1422
handle release()
\rst Resets the internal pointer to nullptr without decreasing the object's reference count.
Definition: pytypes.h:283
Definition: pytypes.h:1167
#define PYBIND11_NAMESPACE_END(name)
Definition: common.h:21
#define PYBIND11_NAMESPACE_BEGIN(name)
Definition: common.h:20
typename std::conditional< B, T, F >::type conditional_t
Definition: common.h:627
return_value_policy
Approach used to cast a previously unknown C++ instance into a Python object.
Definition: common.h:470
constexpr descr< N - 1 > const_name(char const (&text)[N])
Definition: descr.h:60
constexpr descr< 0 > concat()
Definition: descr.h:139
bool same_type(const std::type_info &lhs, const std::type_info &rhs)
Definition: internals.h:114
Internal data structure which holds metadata about a bound function (signature, overloads,...
Definition: attr.h:188
bool load(handle src, bool convert)
Definition: functional.h:26
static handle cast(Func &&f_, return_value_policy policy, handle)
Definition: functional.h:112
PYBIND11_TYPE_CASTER(type, const_name("Callable[[")+concat(make_caster< Args >::name...)+const_name("], ")+make_caster< retval_type >::name+const_name("]"))
conditional_t< std::is_same< Return, void >::value, void_type, Return > retval_type
Definition: functional.h:22
Helper type to replace 'void' in some expressions.
Definition: common.h:773