Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intersection of overloads and std::function<> #1085

Closed
jcelerier opened this issue Sep 13, 2017 · 6 comments
Closed

Intersection of overloads and std::function<> #1085

jcelerier opened this issue Sep 13, 2017 · 6 comments

Comments

@jcelerier
Copy link
Contributor

I'd like to have multiple overloads that take different kinds of functions in parameters:

  .def(
      "add_callback",
      [](foo& addr, std::function<void(int)> clbk) { ... })
  .def(
     "add_callback",
      (foo& addr, std::function<void(foo&, int)> clbk) { ... })

But the following python code fails:

def fun_callback(foo, val):
  print(...)

my_foo.add_callback(fun_callback)

with:

TypeError: fun_callback() missing 1 required positional argument: 'val'

The first overload works, and renaming the second overload to another function name (for instance add_callback2) works too.

Is there a way around this ?

@henryiii
Copy link
Collaborator

henryiii commented Sep 13, 2017

Quick note: you must be compiling in C++14, or at least with a C++14 supporting compiler, in order for the compiler to be able to tell the difference between differing signatures in std::function. This might be related. (I think GCC 4.9 was the first to support it, for example, but PyBind11 supports GCC 4.8, so it might stem from that)

@YannickJadoul
Copy link
Collaborator

Wouldn't the problem be that a Python function cannot 'match a typed overload', in general, because of Python's duck-typing?

@jcelerier
Copy link
Contributor Author

Quick note: you must be compiling in C++14, or at least with a C++14 supporting compiler,

yep, I am (using g++ 7.2).

Wouldn't the problem be that a Python function cannot 'match a typed overload', in general, because of Python's duck-typing?

hmm... yes, that would make sense. If I understand correctly, there is a single "function" type from Python's side ?

@YannickJadoul
Copy link
Collaborator

hmm... yes, that would make sense. If I understand correctly, there is a single "function" type from Python's side ?

I think so. Or not even, actually. There's just 'things that can be called' (i.e., I'm guessing you could perfectly pass an object with the __call__ method implemented). Either way, these things typically only get caught once they are used, in Python.

On the other hand, doesn't Python allow some kind of introspection, either? But then I don't know if pybind uses that.

@YannickJadoul
Copy link
Collaborator

On the other hand, doesn't Python allow some kind of introspection, either? But then I don't know if pybind uses that.

Answer: nope, looking at functional.h.

        if (!isinstance<function>(src))
            return false;

// ...

        value = [func](Args... args) -> Return {
            gil_scoped_acquire acq;
            object retval(func(std::forward<Args>(args)...));
            /* Visual studio 2015 parser issue: need parentheses around this expression */
            return (retval.template cast<Return>());
        };

@jcelerier
Copy link
Contributor Author

okay, I guess I'll just give my function another name ! thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants