FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
pybind11/include/pybind11/functional.h at native_enum_sh · rwgk/pybind11 · GitHub
rwgk
pybind11
Repository navigation
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
pybind11
/
include
/
pybind11
/
functional.h
Copy path
More file actions
More file actions
Latest commit
History
History
History
137 lines (117 loc) · 4.88 KB
Breadcrumbs
pybind11
/
include
/
pybind11
/
functional.h
Copy path
File metadata and controls
137 lines (117 loc) · 4.88 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
pybind11/functional.h: std::function<> support
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#
pragma
once
#
include
"
pybind11.h
"
#
include
<
functional
>
PYBIND11_NAMESPACE_BEGIN
(
PYBIND11_NAMESPACE
)
PYBIND11_NAMESPACE_BEGIN
(detail)
template
<
typename
Return,
typename
... Args>
struct
type_caster
<std::function<Return(Args...)>> {
using
type = std::function<Return(Args...)>;
using
retval_type =
conditional_t
<std::is_same<Return,
void
>::value, void_type, Return>;
using
function_type = Return (*)(Args...);
public:
bool
load
(handle src,
bool
convert) {
if
(src.
is_none
()) {
//
Defer accepting None to other overloads (if we aren't in convert mode):
if
(!convert) {
return
false
;
}
return
true
;
}
if
(!isinstance<function>(src)) {
return
false
;
}
auto
func = reinterpret_borrow<function>(src);
/*
When passing a C++ function as an argument to another C++
function via Python, every function call would normally involve
a full C++ -> Python -> C++ roundtrip, which can be prohibitive.
Here, we try to at least detect the case where the function is
stateless (i.e. function pointer or lambda function without
captured variables), in which case the roundtrip can be avoided.
*/
if
(
auto
cfunc = func.
cpp_function
()) {
auto
*cfunc_self =
PyCFunction_GET_SELF
(cfunc.
ptr
());
if
(cfunc_self ==
nullptr
) {
PyErr_Clear
();
}
else
if
(isinstance<capsule>(cfunc_self)) {
auto
c = reinterpret_borrow<capsule>(cfunc_self);
function_record *rec =
nullptr
;
//
Check that we can safely reinterpret the capsule into a function_record
if
(
detail::is_function_record_capsule
(c)) {
rec = c.
get_pointer
<function_record>();
}
while
(rec !=
nullptr
) {
if
(rec->
is_stateless
&&
same_type
(
typeid
(function_type),
*
reinterpret_cast
<
const
std::type_info *>(rec->
data
[
1
]))) {
struct
capture
{
function_type f;
};
value = ((capture *) &rec->
data
)->
f
;
return
true
;
}
rec = rec->
next
;
}
}
//
PYPY segfaults here when passing builtin function like sum.
//
Raising an fail exception here works to prevent the segfault, but only on gcc.
//
See PR #1413 for full details
}
//
ensure GIL is held during functor destruction
struct
func_handle
{
function f;
#
if
!(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17))
//
This triggers a syntax error under very special conditions (very weird indeed).
explicit
#
endif
func_handle
(function &&f_)
noexcept
: f(std::move(f_)) {
}
func_handle
(
const
func_handle &f_) {
operator
=(f_); }
func_handle &
operator
=(
const
func_handle &f_) {
gil_scoped_acquire acq;
f = f_.
f
;
return
*
this
;
}
~func_handle
() {
gil_scoped_acquire acq;
function
kill_f
(
std::move
(f));
}
};
//
to emulate 'move initialization capture' in C++11
struct
func_wrapper
{
func_handle hfunc;
explicit
func_wrapper
(func_handle &&hf)
noexcept
: hfunc(std::move(hf)) {}
Return
operator
()(Args... args)
const
{
gil_scoped_acquire acq;
//
casts the returned object as a rvalue to the return type
return
hfunc.
f
(std::forward<Args>(args)...).
template
cast
<Return>();
}
};
value =
func_wrapper
(
func_handle
(
std::move
(func)));
return
true
;
}
template
<
typename
Func>
static
handle
cast
(Func &&f_, return_value_policy policy, handle
/*
parent
*/
) {
if
(!f_) {
return
none
().
release
();
}
auto
result = f_.
template
target
<function_type>();
if
(result) {
return
cpp_function
(*result, policy).
release
();
}
return
cpp_function
(std::forward<Func>(f_), policy).
release
();
}
PYBIND11_TYPE_CASTER
(type,
const_name
(
"
Callable[[
"
) + concat(make_caster<Args>::name...)
+ const_name(
"
],
"
) + make_caster<retval_type>::name
+ const_name(
"
]
"
));
};
PYBIND11_NAMESPACE_END
(detail)
PYBIND11_NAMESPACE_END
(
PYBIND11_NAMESPACE
)
Back
|
FazBrowse Home
|
New Git URL