File indexing completed on 2025-02-16 05:12:16
0001 /* 0002 pybind11/functional.h: std::function<> support 0003 0004 Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> 0005 0006 All rights reserved. Use of this source code is governed by a 0007 BSD-style license that can be found in the LICENSE file. 0008 */ 0009 0010 #pragma once 0011 0012 #include "pybind11.h" 0013 #include <functional> 0014 0015 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 0016 PYBIND11_NAMESPACE_BEGIN(detail) 0017 0018 template <typename Return, typename... Args> 0019 struct type_caster<std::function<Return(Args...)>> { 0020 using type = std::function<Return(Args...)>; 0021 using retval_type = conditional_t<std::is_same<Return, void>::value, void_type, Return>; 0022 using function_type = Return (*) (Args...); 0023 0024 public: 0025 bool load(handle src, bool convert) { 0026 if (src.is_none()) { 0027 // Defer accepting None to other overloads (if we aren't in convert mode): 0028 if (!convert) return false; 0029 return true; 0030 } 0031 0032 if (!isinstance<function>(src)) 0033 return false; 0034 0035 auto func = reinterpret_borrow<function>(src); 0036 0037 /* 0038 When passing a C++ function as an argument to another C++ 0039 function via Python, every function call would normally involve 0040 a full C++ -> Python -> C++ roundtrip, which can be prohibitive. 0041 Here, we try to at least detect the case where the function is 0042 stateless (i.e. function pointer or lambda function without 0043 captured variables), in which case the roundtrip can be avoided. 0044 */ 0045 if (auto cfunc = func.cpp_function()) { 0046 auto cfunc_self = PyCFunction_GET_SELF(cfunc.ptr()); 0047 if (isinstance<capsule>(cfunc_self)) { 0048 auto c = reinterpret_borrow<capsule>(cfunc_self); 0049 auto rec = (function_record *) c; 0050 0051 while (rec != nullptr) { 0052 if (rec->is_stateless 0053 && same_type(typeid(function_type), 0054 *reinterpret_cast<const std::type_info *>(rec->data[1]))) { 0055 struct capture { 0056 function_type f; 0057 }; 0058 value = ((capture *) &rec->data)->f; 0059 return true; 0060 } 0061 rec = rec->next; 0062 } 0063 } 0064 // PYPY segfaults here when passing builtin function like sum. 0065 // Raising an fail exception here works to prevent the segfault, but only on gcc. 0066 // See PR #1413 for full details 0067 } 0068 0069 // ensure GIL is held during functor destruction 0070 struct func_handle { 0071 function f; 0072 #if !(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17)) 0073 // This triggers a syntax error under very special conditions (very weird indeed). 0074 explicit 0075 #endif 0076 func_handle(function &&f_) noexcept : f(std::move(f_)) {} 0077 func_handle(const func_handle &f_) { operator=(f_); } 0078 func_handle &operator=(const func_handle &f_) { 0079 gil_scoped_acquire acq; 0080 f = f_.f; 0081 return *this; 0082 } 0083 ~func_handle() { 0084 gil_scoped_acquire acq; 0085 function kill_f(std::move(f)); 0086 } 0087 }; 0088 0089 // to emulate 'move initialization capture' in C++11 0090 struct func_wrapper { 0091 func_handle hfunc; 0092 explicit func_wrapper(func_handle &&hf) noexcept : hfunc(std::move(hf)) {} 0093 Return operator()(Args... args) const { 0094 gil_scoped_acquire acq; 0095 object retval(hfunc.f(std::forward<Args>(args)...)); 0096 /* Visual studio 2015 parser issue: need parentheses around this expression */ 0097 return (retval.template cast<Return>()); 0098 } 0099 }; 0100 0101 value = func_wrapper(func_handle(std::move(func))); 0102 return true; 0103 } 0104 0105 template <typename Func> 0106 static handle cast(Func &&f_, return_value_policy policy, handle /* parent */) { 0107 if (!f_) 0108 return none().inc_ref(); 0109 0110 auto result = f_.template target<function_type>(); 0111 if (result) 0112 return cpp_function(*result, policy).release(); 0113 return cpp_function(std::forward<Func>(f_), policy).release(); 0114 } 0115 0116 PYBIND11_TYPE_CASTER(type, const_name("Callable[[") + concat(make_caster<Args>::name...) + const_name("], ") 0117 + make_caster<retval_type>::name + const_name("]")); 0118 }; 0119 0120 PYBIND11_NAMESPACE_END(detail) 0121 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)