pybind / pybind/pybind11

wrapping a std::function as class member

Open
#1,275 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
18k
Forks
2.3k
Avg merge
5d 17h
Merged PRs (30d)
10

Description

I got stuck completly with the following, when trying to wrap a class with a std::function member.
The following code produces an error inside pybind11.h.
Obviously, something goes wrong with a std::function object as a class member.

Binding Code:

#include <pybind11/pybind11.h>
#include <pybind11/functional.h>
#include "pyBind11Test.hpp" 

namespace py = pybind11;

PYBIND11_MODULE(stuff, module) {
      
   py::class_<Stuff> (module, "Stuff")
      .def( py::init( []
                      (const int n)
                      {return std::unique_ptr<Stuff> (new Stuff(n)); } ))
      .def("getNr", &Stuff::getNr);
}

Class declaration pyBind11Test.hpp

#include <iostream>
#include <functional>

class Stuff {
   private:
      double retOne();
      double retTwo();
   public:
      Stuff(const int n);
      std::function<double()> getNr;
};

Class definition pyBind11Test.cpp

#include "pyBind11Test.hpp"

Stuff::Stuff(const int n) {
   switch(n) {
      case 1 : {
         std::function<double()> getNr = [this](){return this->retOne();};
      }
      case 2 : {
         std::function<double()> getNr = std::bind(&Stuff::retTwo, this);
         // std::function<double()> getNr = [this](){return this->retTwo();};
      }
      default : {
         exit(1);
      }
   }
}

double Stuff::retOne(){
   return 1.;
}

double Stuff::retTwo(){
   return 2.;
}

The compiler terminates withe the following error message:

g++ -std=c++14 -fPIC -Wall -I/usr/include/python3.5m -I/usr/local/include/python3.5 -I/usr/include -o ./wrapPyBind11Test.o -c ./wrapPyBind11Test.cpp

In file included from ./wrapPyBind11Test.cpp:3:0:
/usr/local/include/python3.5/pybind11/pybind11.h: In instantiation of ‘pybind11::class_<type_, options>& pybind11::class_<type_, options>::def(const char*, Func&&, const Extra& ...) [with Func = std::function<double()> Stuff::*; Extra = {}; type_ = Stuff; options = {}]’:
./wrapPyBind11Test.cpp:22:36:   required from here
/usr/local/include/python3.5/pybind11/pybind11.h:1086:73: error: no matching function for call to ‘pybind11::cpp_function::cpp_function(std::function<double()> Stuff::*, pybind11::name, pybind11::is_method, pybind11::sibling)’
                         sibling(getattr(*this, name_, none())), extra...);
                                                                         ^
In file included from ./wrapPyBind11Test.cpp:3:0:
/usr/local/include/python3.5/pybind11/pybind11.h:78:5: note: candidate: template<class Return, class Class, class ... Arg, class ... Extra> pybind11::cpp_function::cpp_function(Return (Class::*)(Arg ...) const, const Extra& ...)
     cpp_function(Return (Class::*f)(Arg...) const, const Extra&... extra) {
     ^
/usr/local/include/python3.5/pybind11/pybind11.h:78:5: note:   template argument deduction/substitution failed:
In file included from ./wrapPyBind11Test.cpp:3:0:
/usr/local/include/python3.5/pybind11/pybind11.h:1086:73: note:   mismatched types ‘Return (Class::*)(Arg ...) const’ and ‘std::function<double()> Stuff::*’
                         sibling(getattr(*this, name_, none())), extra...);
                                                                         ^
In file included from ./wrapPyBind11Test.cpp:3:0:
/usr/local/include/python3.5/pybind11/pybind11.h:71:5: note: candidate: template<class Return, class Class, class ... Arg, class ... Extra> pybind11::cpp_function::cpp_function(Return (Class::*)(Arg ...), const Extra& ...)
     cpp_function(Return (Class::*f)(Arg...), const Extra&... extra) {
     ^
/usr/local/include/python3.5/pybind11/pybind11.h:71:5: note:   template argument deduction/substitution failed:
In file included from ./wrapPyBind11Test.cpp:3:0:
/usr/local/include/python3.5/pybind11/pybind11.h:1086:73: note:   mismatched types ‘Return (Class::*)(Arg ...)’ and ‘std::function<double()> Stuff::*’
                         sibling(getattr(*this, name_, none())), extra...);
                                                                         ^
In file included from ./wrapPyBind11Test.cpp:3:0:
/usr/local/include/python3.5/pybind11/pybind11.h:64:5: note: candidate: template<class Func, class ... Extra, class> pybind11::cpp_function::cpp_function(Func&&, const Extra& ...)
     cpp_function(Func &&f, const Extra&... extra) {
     ^
/usr/local/include/python3.5/pybind11/pybind11.h:64:5: note:   template argument deduction/substitution failed:
/usr/local/include/python3.5/pybind11/pybind11.h:57:5: note: candidate: template<class Return, class ... Args, class ... Extra> pybind11::cpp_function::cpp_function(Return (*)(Args ...), const Extra& ...)
     cpp_function(Return (*f)(Args...), const Extra&... extra) {
     ^
/usr/local/include/python3.5/pybind11/pybind11.h:57:5: note:   template argument deduction/substitution failed:
In file included from ./wrapPyBind11Test.cpp:3:0:
/usr/local/include/python3.5/pybind11/pybind11.h:1086:73: note:   mismatched types ‘Return (*)(Args ...)’ and ‘std::function<double()> Stuff::*’
                         sibling(getattr(*this, name_, none())), extra...);
                                                                         ^
In file included from ./wrapPyBind11Test.cpp:3:0:
/usr/local/include/python3.5/pybind11/pybind11.h:53:5: note: candidate: pybind11::cpp_function::cpp_function()
     cpp_function() { }
     ^
/usr/local/include/python3.5/pybind11/pybind11.h:53:5: note:   candidate expects 0 arguments, 4 provided
/usr/local/include/python3.5/pybind11/pybind11.h:51:7: note: candidate: pybind11::cpp_function::cpp_function(const pybind11::cpp_function&)
 class cpp_function : public function {
       ^
/usr/local/include/python3.5/pybind11/pybind11.h:51:7: note:   candidate expects 1 argument, 4 provided
/usr/local/include/python3.5/pybind11/pybind11.h:51:7: note: candidate: pybind11::cpp_function::cpp_function(pybind11::cpp_function&&)
/usr/local/include/python3.5/pybind11/pybind11.h:51:7: note:   candidate expects 1 argument, 4 provided
makefile:24: recipe for target 'wrapPyBind11Test.o' failed
make: *** [wrapPyBind11Test.o] Error 1

Any ideas?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the compiler error from the binding code and inspect the member declaration in pyBind11Test.hpp, the constructor in pyBind11Test.cpp, and the reported overloads in pybind11.h. Determine whether the failure is caused by binding a std::function data member or by the example itself; done means documenting a confirmed cause and a focused resolution or limitation.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, python
Domain
developer-experience
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.