functional.h
Go to the documentation of this file.
1 /*
2  pybind11/functional.h: std::function<> support
3 
4  Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5 
6  All rights reserved. Use of this source code is governed by a
7  BSD-style license that can be found in the LICENSE file.
8 */
9 
10 #pragma once
11 
12 #include "pybind11.h"
13 
14 #include <functional>
15 
18 
19 template <typename Return, typename... Args>
20 struct type_caster<std::function<Return(Args...)>> {
21  using type = std::function<Return(Args...)>;
23  using function_type = Return (*)(Args...);
24 
25 public:
26  bool load(handle src, bool convert) {
27  if (src.is_none()) {
28  // Defer accepting None to other overloads (if we aren't in convert mode):
29  if (!convert) {
30  return false;
31  }
32  return true;
33  }
34 
35  if (!isinstance<function>(src)) {
36  return false;
37  }
38 
39  auto func = reinterpret_borrow<function>(src);
40 
41  /*
42  When passing a C++ function as an argument to another C++
43  function via Python, every function call would normally involve
44  a full C++ -> Python -> C++ roundtrip, which can be prohibitive.
45  Here, we try to at least detect the case where the function is
46  stateless (i.e. function pointer or lambda function without
47  captured variables), in which case the roundtrip can be avoided.
48  */
49  if (auto cfunc = func.cpp_function()) {
50  auto *cfunc_self = PyCFunction_GET_SELF(cfunc.ptr());
51  if (cfunc_self == nullptr) {
52  PyErr_Clear();
53  } else if (isinstance<capsule>(cfunc_self)) {
54  auto c = reinterpret_borrow<capsule>(cfunc_self);
55 
56  function_record *rec = nullptr;
57  // Check that we can safely reinterpret the capsule into a function_record
59  rec = c.get_pointer<function_record>();
60  }
61 
62  while (rec != nullptr) {
63  if (rec->is_stateless
64  && same_type(typeid(function_type),
65  *reinterpret_cast<const std::type_info *>(rec->data[1]))) {
66  struct capture {
68  };
69  value = ((capture *) &rec->data)->f;
70  return true;
71  }
72  rec = rec->next;
73  }
74  }
75  // PYPY segfaults here when passing builtin function like sum.
76  // Raising an fail exception here works to prevent the segfault, but only on gcc.
77  // See PR #1413 for full details
78  }
79 
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_) {
93  f = f_.f;
94  return *this;
95  }
96  ~func_handle() {
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)));
114  return true;
115  }
116 
117  template <typename Func>
118  static handle cast(Func &&f_, return_value_policy policy, handle /* parent */) {
119  if (!f_) {
120  return none().release();
121  }
122 
123  auto result = f_.template target<function_type>();
124  if (result) {
125  return cpp_function(*result, policy).release();
126  }
127  return cpp_function(std::forward<Func>(f_), policy).release();
128  }
129 
131  const_name("Callable[[") + concat(make_caster<Args>::name...)
133  + const_name("]"));
134 };
135 
function_record
Definition: attr.h:191
const_name
constexpr descr< N - 1 > const_name(char const (&text)[N])
Definition: descr.h:60
return_value_policy
return_value_policy
Approach used to cast a previously unknown C++ instance into a Python object.
Definition: wrap/pybind11/include/pybind11/detail/common.h:485
c
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
type_caster_generic::value
void * value
Definition: type_caster_base.h:795
PYBIND11_NAMESPACE_END
#define PYBIND11_NAMESPACE_END(name)
Definition: wrap/pybind11/include/pybind11/detail/common.h:80
type
Definition: pytypes.h:1491
detail
Definition: testSerializationNonlinear.cpp:70
PYBIND11_NAMESPACE_BEGIN
#define PYBIND11_NAMESPACE_BEGIN(name)
Definition: wrap/pybind11/include/pybind11/detail/common.h:76
type_caster< std::function< Return(Args...)> >::function_type
Return(*)(Args...) function_type
Definition: functional.h:23
result
Values result
Definition: OdometryOptimize.cpp:8
function_record::data
void * data[3]
Storage for the wrapped function pointer and captured data, if any.
Definition: attr.h:213
conditional_t
typename std::conditional< B, T, F >::type conditional_t
Definition: wrap/pybind11/include/pybind11/detail/common.h:642
same_type
bool same_type(const std::type_info &lhs, const std::type_info &rhs)
Definition: internals.h:132
handle
Definition: pytypes.h:217
type_caster
Definition: cast.h:38
type_caster< std::function< Return(Args...)> >::retval_type
conditional_t< std::is_same< Return, void >::value, void_type, Return > retval_type
Definition: functional.h:22
operator()
internal::enable_if< internal::valid_indexed_view_overload< RowIndices, ColIndices >::value &&internal::traits< typename EIGEN_INDEXED_VIEW_METHOD_TYPE< RowIndices, ColIndices >::type >::ReturnAsIndexedView, typename EIGEN_INDEXED_VIEW_METHOD_TYPE< RowIndices, ColIndices >::type >::type operator()(const RowIndices &rowIndices, const ColIndices &colIndices) EIGEN_INDEXED_VIEW_METHOD_CONST
Definition: IndexedViewMethods.h:73
object::release
handle release()
Definition: pytypes.h:368
conftest.capture
def capture(capsys)
Definition: conftest.py:138
function_record::next
function_record * next
Pointer to next overload.
Definition: attr.h:268
type_caster< std::function< Return(Args...)> >::cast
static handle cast(Func &&f_, return_value_policy policy, handle)
Definition: functional.h:118
PYBIND11_NAMESPACE
Definition: test_custom_type_casters.cpp:24
concat
constexpr descr< 0 > concat()
Definition: descr.h:139
cpp_function
Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object.
Definition: pybind11.h:82
gil_scoped_acquire
Definition: gil.h:215
is_function_record_capsule
bool is_function_record_capsule(const capsule &cap)
Definition: internals.h:619
function_record::is_stateless
bool is_stateless
True if this is a stateless function pointer.
Definition: attr.h:228
tree::f
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
Definition: testExpression.cpp:218
PYBIND11_TYPE_CASTER
#define PYBIND11_TYPE_CASTER(type, py_name)
Definition: cast.h:85
pybind11.h
std
Definition: BFloat16.h:88
void_type
Helper type to replace 'void' in some expressions.
Definition: wrap/pybind11/include/pybind11/detail/common.h:801
args
Definition: pytypes.h:2163
function
Definition: pytypes.h:2205
type_caster< std::function< Return(Args...)> >::load
bool load(handle src, bool convert)
Definition: functional.h:26
none
Definition: pytypes.h:1744
func
Definition: benchGeometry.cpp:23
gtsam::convert
static BinaryMeasurement< Rot3 > convert(const BetweenFactor< Pose3 >::shared_ptr &f)
Definition: ShonanAveraging.cpp:998


gtsam
Author(s):
autogenerated on Thu Jun 13 2024 03:02:23