I simply have a function object:

boost::function<int(int)> func = /** ... **/;

And want to expose it to Python with a docstring.
But the obvious:

def("func", func, "Some boring documentation goes here.");

Fails with an amusing ~2500 lines message.

Any ideas?


Edit: I made other tests:

def("func", func); // doesn't compile

def("func",
   make_function(
     func,
     default_call_policies(),
     vector<int,int>()
   )
); // compiles

def("func",
   make_function(
     func,
     default_call_policies(),
     vector<int,int>()
   ),
   "Some boring documentation goes here"
); // doesn't compile
有帮助吗?

解决方案

The boost::python::def() documentation mentions being able to provide a docstring only when provided a non-null function or member function pointer. One solution is to wrap the function object call in a function:

#include <boost/function.hpp>
#include <boost/python.hpp>

int times_two(int x) { return x * 2; }

boost::function<int(int)> func = &times_two;

int times_two_wrap(int x) { return func(x); }

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::def("times_two", &times_two_wrap,
              "returns two times the supplied value");
}

Interactive usage:

>>> import example
>>> assert(6 == example.times_two(3))
>>> print help(example.times_two)

times_two( (int)arg1) -> int :
    returns two times the supplied value

    C++ signature :
        int times_two(int)
>>>

Boost.Python has multiple API layers. The highest layer is mostly documented, but it makes use of a less-documented lower-level API. In this particular case, it looks as though the higher-level API is poorly forwarding to the lower-level API. One could instead create a python function using boost::python::make_function(), then use the lower-level boost::python::objects::add_to_namespace() function, as demonstrated below:

#include <boost/function.hpp>
#include <boost/python.hpp>

int times_two(int x) { return x * 2; }

boost::function<int(int)> func = &times_two;

BOOST_PYTHON_MODULE(example)
{
   namespace python = boost::python;
   // Wrap the functor in a Python object.
   python::object py_func = python::make_function(
     func,
     python::default_call_policies(),
     boost::mpl::vector<int, int>());
   // Add the function directly to the namespace.
   python::objects::add_to_namespace(
     python::scope(), // current namespace,
     "times_two",     // function name,
     py_func,         // function,
     "returns two times the supplied value");
}

This produces the same output with the interactive usage. The only notable behavioral difference between the two approaches is that the first example enables one to change the underlying implementation at runtime by assigning a new value to func.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top