|
15 | 15 |
|
16 | 16 | PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
17 | 17 | PYBIND11_NAMESPACE_BEGIN(detail)
|
| 18 | +PYBIND11_NAMESPACE_BEGIN(type_caster_std_function_specializations) |
| 19 | + |
| 20 | +// ensure GIL is held during functor destruction |
| 21 | +struct func_handle { |
| 22 | + function f; |
| 23 | +#if !(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17)) |
| 24 | + // This triggers a syntax error under very special conditions (very weird indeed). |
| 25 | + explicit |
| 26 | +#endif |
| 27 | + func_handle(function &&f_) noexcept |
| 28 | + : f(std::move(f_)) { |
| 29 | + } |
| 30 | + func_handle(const func_handle &f_) { operator=(f_); } |
| 31 | + func_handle &operator=(const func_handle &f_) { |
| 32 | + gil_scoped_acquire acq; |
| 33 | + f = f_.f; |
| 34 | + return *this; |
| 35 | + } |
| 36 | + ~func_handle() { |
| 37 | + gil_scoped_acquire acq; |
| 38 | + function kill_f(std::move(f)); |
| 39 | + } |
| 40 | +}; |
| 41 | + |
| 42 | +// to emulate 'move initialization capture' in C++11 |
| 43 | +struct func_wrapper_base { |
| 44 | + func_handle hfunc; |
| 45 | + explicit func_wrapper_base(func_handle &&hf) noexcept : hfunc(std::move(hf)) {} |
| 46 | +}; |
| 47 | + |
| 48 | +template <typename Return, typename... Args> |
| 49 | +struct func_wrapper : func_wrapper_base { |
| 50 | + using func_wrapper_base::func_wrapper_base; |
| 51 | + Return operator()(Args... args) const { |
| 52 | + gil_scoped_acquire acq; |
| 53 | + // casts the returned object as a rvalue to the return type |
| 54 | + return hfunc.f(std::forward<Args>(args)...).template cast<Return>(); |
| 55 | + } |
| 56 | +}; |
| 57 | + |
| 58 | +PYBIND11_NAMESPACE_END(type_caster_std_function_specializations) |
18 | 59 |
|
19 | 60 | template <typename Return, typename... Args>
|
20 | 61 | struct type_caster<std::function<Return(Args...)>> {
|
@@ -77,40 +118,8 @@ struct type_caster<std::function<Return(Args...)>> {
|
77 | 118 | // See PR #1413 for full details
|
78 | 119 | }
|
79 | 120 |
|
80 |
| - // ensure GIL is held during functor destruction |
81 |
| - struct func_handle { |
82 |
| - function f; |
83 |
| -#if !(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17)) |
84 |
| - // This triggers a syntax error under very special conditions (very weird indeed). |
85 |
| - explicit |
86 |
| -#endif |
87 |
| - func_handle(function &&f_) noexcept |
88 |
| - : f(std::move(f_)) { |
89 |
| - } |
90 |
| - func_handle(const func_handle &f_) { operator=(f_); } |
91 |
| - func_handle &operator=(const func_handle &f_) { |
92 |
| - gil_scoped_acquire acq; |
93 |
| - f = f_.f; |
94 |
| - return *this; |
95 |
| - } |
96 |
| - ~func_handle() { |
97 |
| - gil_scoped_acquire acq; |
98 |
| - function kill_f(std::move(f)); |
99 |
| - } |
100 |
| - }; |
101 |
| - |
102 |
| - // to emulate 'move initialization capture' in C++11 |
103 |
| - struct func_wrapper { |
104 |
| - func_handle hfunc; |
105 |
| - explicit func_wrapper(func_handle &&hf) noexcept : hfunc(std::move(hf)) {} |
106 |
| - Return operator()(Args... args) const { |
107 |
| - gil_scoped_acquire acq; |
108 |
| - // casts the returned object as a rvalue to the return type |
109 |
| - return hfunc.f(std::forward<Args>(args)...).template cast<Return>(); |
110 |
| - } |
111 |
| - }; |
112 |
| - |
113 |
| - value = func_wrapper(func_handle(std::move(func))); |
| 121 | + value = type_caster_std_function_specializations::func_wrapper<Return, Args...>( |
| 122 | + type_caster_std_function_specializations::func_handle(std::move(func))); |
114 | 123 | return true;
|
115 | 124 | }
|
116 | 125 |
|
|
0 commit comments