Skip to content

Commit

Permalink
Allow function pointer extraction from overloaded functions (#2944)
Browse files Browse the repository at this point in the history
* Add a failure test for overloaded functions

* Allow function pointer extraction from overloaded functions
  • Loading branch information
otamachan committed Apr 13, 2021
1 parent e0c1dad commit 6709abb
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 5 deletions.
16 changes: 11 additions & 5 deletions include/pybind11/functional.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,17 @@ struct type_caster<std::function<Return(Args...)>> {
auto c = reinterpret_borrow<capsule>(PyCFunction_GET_SELF(cfunc.ptr()));
auto rec = (function_record *) c;

if (rec && rec->is_stateless &&
same_type(typeid(function_type), *reinterpret_cast<const std::type_info *>(rec->data[1]))) {
struct capture { function_type f; };
value = ((capture *) &rec->data)->f;
return true;
while (rec != nullptr) {
if (rec->is_stateless
&& same_type(typeid(function_type),
*reinterpret_cast<const std::type_info *>(rec->data[1]))) {
struct capture {
function_type f;
};
value = ((capture *) &rec->data)->f;
return true;
}
rec = rec->next;
}
}

Expand Down
2 changes: 2 additions & 0 deletions tests/test_callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ TEST_SUBMODULE(callbacks, m) {
// test_cpp_function_roundtrip
/* Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer */
m.def("dummy_function", &dummy_function);
m.def("dummy_function_overloaded", [](int i, int j) { return i + j; });
m.def("dummy_function_overloaded", &dummy_function);
m.def("dummy_function2", [](int i, int j) { return i + j; });
m.def("roundtrip", [](std::function<int(int)> f, bool expect_none = false) {
if (expect_none && f)
Expand Down
4 changes: 4 additions & 0 deletions tests/test_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ def test_cpp_function_roundtrip():
m.test_dummy_function(m.roundtrip(m.dummy_function))
== "matches dummy_function: eval(1) = 2"
)
assert (
m.test_dummy_function(m.dummy_function_overloaded)
== "matches dummy_function: eval(1) = 2"
)
assert m.roundtrip(None, expect_none=True) is None
assert (
m.test_dummy_function(lambda x: x + 2)
Expand Down

0 comments on commit 6709abb

Please sign in to comment.