Search code examples
c++boost-python

Boost python passing named parameter to member class


I have the following struct:

struct StuffMaker {

  static std::string makeStuff(po::dict options = {})
  {

    //makes some stuff
  }

};

I want to expose it in my python module to do some stuff:


BOOST_PYTHON_MODULE(stuffMakers)
{
  po::class_<StuffMaker>("StuffMaker")
    .def("create", &StuffMaker::makeStuff, (arg("options")));
}

however when I compile the interpreter and pass the following code:

import stuffMakers
maker = stuffMakers.StuffMaker()
maker.makeStuff(options = {})

I am getting the type error of first parameter, the expected is dict of options, however my cpp is getting the "self" reference - so a StuffMaker class as first parameter. And basically this is my question, how do I ignore the first parameter in the c++ binding or what do I put in front of "arg" in definition to handle the "self" parameter correctly?

The error is as follows:

Traceback (most recent call last):
  File "<string>", line 6, in <module>
Boost.Python.ArgumentError: Python argument types in
    StuffMaker.makeStuff(StuffMaker)
did not match C++ signature:
    create(boost::python::dict options)


Solution

  • In order to pass the self parameter through you have at least 2 working choices of signature:

    struct StuffMaker {
    
      static std::string makeStuff(StuffMaker self, po::dict options = {})
      {
    
        //makes some stuff
      }
    
      //alternatively
      static std::string makeStuff(StuffMaker* self, po::dict options = {})
      {
    
        //makes some stuff
      }
    };
    

    This signature works fine, the registration takes care of implicit parameter automatically, so to register the named parameter all you need to do is the following change:

    BOOST_PYTHON_MODULE(geometry_creators)
    {
      po::class_<StuffMaker>("StuffMaker")
        .def("makeStuff", &StuffMaker::makeStuff, (po::arg("options")), "do some stuff with named parameter");
    }
    

    The first argument in the arguments list is added automatically so there is no need for implicitly adding it in the def registartion.