I want to bind a function that takes a lambda (std::function) as an argument. The lambda itself has a reference to an abstract type as an argument. When I attempt to invoke the function in python, I get an error because the abstract type is not copyable. Below is a small example. I have an interface IFoo which is abstract and its concrete implementation Foo. I then have a function evaluate which takes as an argument a std::function<void(IFoo&)>. I would prefer not to expose the concrete implementation in the python binding so I only bind the interface. #include <iostream> #include <pybind11/pybind11.h> #include <pybind11/functional.h> namespace py = pybind11; class IFoo { public: virtual ~IFoo() = default; virtual void setValue(int a) = 0; }; class Foo : public IFoo { public: ~Foo() override = default; void setValue(int a) override { m_a = a; } int getValue() const { return m_a; } protected: int m_a{18}; }; int evaluate(std::function<void(IFoo&)>&& callback) { Foo foo; callback(foo); return foo.getValue() + 34; } PYBIND11_MODULE(libbindtest, module) { py::class_< IFoo >(module, "Foo").def("setValue", &IFoo::setValue); module.def("evaluate", &evaluate); } /* int main (int, char**) { int res1 = evaluate([](auto& foo){ foo.setValue(22); }); int res2 = evaluate([](auto&){}); std::cout << "Res1: " << res1 << " Res2: " << res2 << std::endl; return 0; } */ This builds fine and runs with this definition of main. My python looks like import libbindtest as bt def foo_operator(foo: bt.Foo): foo.setValue(22) x = bt.evaluate(foo_operator) With this, I get the error Traceback (most recent call last): File "/path/to/bindtest.py", line 6, in <module> x = bt.evaluate(foo_operator) RuntimeError: return_value_policy = copy, but type IFoo is non-copyable! I don't understand why IFoo needs to be copyable here. If I change the function definition to int evaluate(std::function<void(IFoo*)>&& callback) then everything works fine. Does someone know what I'm missing here. Continue reading...