|
9 | 9 |
|
10 | 10 | #pragma once |
11 | 11 |
|
| 12 | +#define PYBIND11_HAS_TYPE_CASTER_STD_FUNCTION_SPECIALIZATIONS |
| 13 | + |
12 | 14 | #include "pybind11.h" |
13 | 15 |
|
14 | 16 | #include <functional> |
15 | 17 |
|
16 | 18 | PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) |
17 | 19 | PYBIND11_NAMESPACE_BEGIN(detail) |
| 20 | +PYBIND11_NAMESPACE_BEGIN(type_caster_std_function_specializations) |
| 21 | + |
| 22 | +// ensure GIL is held during functor destruction |
| 23 | +struct func_handle { |
| 24 | + function f; |
| 25 | +#if !(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17)) |
| 26 | + // This triggers a syntax error under very special conditions (very weird indeed). |
| 27 | + explicit |
| 28 | +#endif |
| 29 | + func_handle(function &&f_) noexcept |
| 30 | + : f(std::move(f_)) { |
| 31 | + } |
| 32 | + func_handle(const func_handle &f_) { operator=(f_); } |
| 33 | + func_handle &operator=(const func_handle &f_) { |
| 34 | + gil_scoped_acquire acq; |
| 35 | + f = f_.f; |
| 36 | + return *this; |
| 37 | + } |
| 38 | + ~func_handle() { |
| 39 | + gil_scoped_acquire acq; |
| 40 | + function kill_f(std::move(f)); |
| 41 | + } |
| 42 | +}; |
| 43 | + |
| 44 | +// to emulate 'move initialization capture' in C++11 |
| 45 | +struct func_wrapper_base { |
| 46 | + func_handle hfunc; |
| 47 | + explicit func_wrapper_base(func_handle &&hf) noexcept : hfunc(std::move(hf)) {} |
| 48 | +}; |
| 49 | + |
| 50 | +template <typename Return, typename... Args> |
| 51 | +struct func_wrapper : func_wrapper_base { |
| 52 | + using func_wrapper_base::func_wrapper_base; |
| 53 | + Return operator()(Args... args) const { |
| 54 | + gil_scoped_acquire acq; |
| 55 | + // casts the returned object as a rvalue to the return type |
| 56 | + return hfunc.f(std::forward<Args>(args)...).template cast<Return>(); |
| 57 | + } |
| 58 | +}; |
| 59 | + |
| 60 | +PYBIND11_NAMESPACE_END(type_caster_std_function_specializations) |
18 | 61 |
|
19 | 62 | template <typename Return, typename... Args> |
20 | 63 | struct type_caster<std::function<Return(Args...)>> { |
@@ -77,40 +120,8 @@ struct type_caster<std::function<Return(Args...)>> { |
77 | 120 | // See PR #1413 for full details |
78 | 121 | } |
79 | 122 |
|
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))); |
| 123 | + value = type_caster_std_function_specializations::func_wrapper<Return, Args...>( |
| 124 | + type_caster_std_function_specializations::func_handle(std::move(func))); |
114 | 125 | return true; |
115 | 126 | } |
116 | 127 |
|
|
0 commit comments