|
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(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