Skip to content

Commit

Permalink
Clean up tests + remove ifdef guards
Browse files Browse the repository at this point in the history
  • Loading branch information
EthanSteinberg committed Oct 20, 2022
1 parent a66dec8 commit 8549ef2
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 17 deletions.
18 changes: 8 additions & 10 deletions include/pybind11/functional.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,14 @@ struct type_caster<std::function<Return(Args...)>> {

auto func = reinterpret_borrow<function>(src);

/*
When passing a C++ function as an argument to another C++
function via Python, every function call would normally involve
a full C++ -> Python -> C++ roundtrip, which can be prohibitive.
Here, we try to at least detect the case where the function is
stateless (i.e. function pointer or lambda function without
captured variables), in which case the roundtrip can be avoided.
*/
#ifndef BAD
/*
When passing a C++ function as an argument to another C++
function via Python, every function call would normally involve
a full C++ -> Python -> C++ roundtrip, which can be prohibitive.
Here, we try to at least detect the case where the function is
stateless (i.e. function pointer or lambda function without
captured variables), in which case the roundtrip can be avoided.
*/
if (auto cfunc = func.cpp_function()) {
auto *cfunc_self = PyCFunction_GET_SELF(cfunc.ptr());
if (cfunc_self == nullptr) {
Expand Down Expand Up @@ -80,7 +79,6 @@ struct type_caster<std::function<Return(Args...)>> {
// Raising an fail exception here works to prevent the segfault, but only on gcc.
// See PR #1413 for full details
}
#endif

// ensure GIL is held during functor destruction
struct func_handle {
Expand Down
18 changes: 14 additions & 4 deletions tests/test_callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,15 @@ TEST_SUBMODULE(callbacks, m) {

def.ml_name = "example_name";
def.ml_doc = "Example doc";
def.ml_meth = [](PyObject *, PyObject *) -> PyObject * {
auto result = py::cast(20);
def.ml_meth = [](PyObject *, PyObject *args) -> PyObject * {
if (PyTuple_Size(args) != 1) {
throw std::runtime_error("Invalid number of arguments for example_name");
}
PyObject *first = PyTuple_GetItem(args, 0);
if (!PyLong_Check(first)) {
throw std::runtime_error("Invalid argument to example_name");
}
auto result = py::cast(PyLong_AsLong(first) * 9);
return result.release().ptr();
};
def.ml_flags = METH_VARARGS;
Expand All @@ -255,6 +262,9 @@ TEST_SUBMODULE(callbacks, m) {
constexpr const char *rec_capsule_name = "CUSTOM_REC_CAPSULE";
py::capsule rec_capsule(std::malloc(1), [](void *data) { std::free(data); });
rec_capsule.set_name(rec_capsule_name);
py::handle m_ptr = PyCFunction_New(&def, rec_capsule.ptr());
m.add_object("custom_function", m_ptr);
m.add_object("custom_function", PyCFunction_New(&def, rec_capsule.ptr()));

// rec_capsule with nullptr name
py::capsule rec_capsule2(std::malloc(1), [](void *data) { std::free(data); });
m.add_object("custom_function2", PyCFunction_New(&def, rec_capsule2.ptr()));
}
8 changes: 5 additions & 3 deletions tests/test_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ def test_callback_num_times():


def test_custom_func():
func = m.custom_function
assert func() == 20
_ = m.roundtrip(func)
assert m.custom_function(4) == 36
assert m.roundtrip(m.custom_function)(4) == 36

assert m.custom_function2(3) == 27
assert m.roundtrip(m.custom_function2)(3) == 27

0 comments on commit 8549ef2

Please sign in to comment.