[BUG]: Incompatible function arguments when using py::function with default parameter
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 18k
- Forks
- 2.3k
- Avg merge
- 5d 17h
- Merged PRs (30d)
- 10
Description
Required prerequisites
- Make sure you've read the documentation. Your issue may be addressed there.
- Search the issue tracker and Discussions to verify that this hasn't already been reported. +1 or comment there if it has.
- Consider asking first in the Gitter chat room or in a Discussion.
What version (or hash if on master) of pybind11 are you using?
2.11.1
Problem description
When setting up a function that takes a py::function as an input argument AND which lets that argument default to nullptr or py::none(), that function cannot be used from Python with default arguments.
The workaround is to use py::object and just work with it as if it were a py::function.
A similar issue was reported previously in https://github.com/pybind/pybind11/issues/3205, but for some reason that issue was closed. It's worth noting that in my code example I set the default argument to nullptr but we see the same behavior if the default argument is py::none(). If the default argument is py::object() or py::function() then you get the issue reported in #3205, namely that we cannot even import the function because we get the error "cannot convert default argument in func2 into a Python object (type not registered yet?)"
Reproducible example code
#include <pybind11/pybind11.h>
namespace py = pybind11;
using namespace pybind11::literals;
PYBIND11_MODULE(example, m) {
m.def("func1", [](py::object func_to_call){}, "docstring", "func_to_call"_a=nullptr);
m.def("func2", [](py::function func_to_call){}, "docstring", "func_to_call"_a=nullptr);
/*Python:
from example import func1, func2
func1(lambda x: x) # works
func1() # works
func2(lambda x: x) # works
func2() # incompatible argument error
*/
}
Is this a regression? Put the last known working version here if it is.
Not a regression
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the pybind11/pybind11.h binding entry point and the provided PYBIND11_MODULE example, comparing func1's py::object default handling with func2's py::function handling. Reproduce the incompatible-argument error for func2() and verify that the default nullptr or py::none() is accepted without changing the working behavior of func1().
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, python
- Domain
- api
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100