0

I want to implement and use some class Base. In Python it would be like that:

class Base:
    def Enumerate(self):
        d = []
        for attr in dir(self):
            if not attr.startswith('__') and not callable(getattr(self, attr)):
                d.append(attr)
        return d

class One(Base):
    hello = "world"

class Two(Base):
    foo = "bar"

arr = [One(), Two()]

arr[0].Enumerate()
arr[1].Enumerate()

But I want to implement Base class in C++ using boost::python.

I've googled a lot, but didn't found anything. Looks like something related to boost::python::wrapper.

Could someone point me the way of how it could be done?

2r2w
  • 1,384
  • 1
  • 12
  • 29
  • First you could see here [docs using inheritance](http://www.boost.org/doc/libs/1_54_0/libs/python/doc/tutorial/doc/html/python/exposing.html) – Katsu Sep 17 '13 at 09:06

1 Answers1

2

If you are not familiar with Boost.Python, then the tutorial is a good place to start. Beyond that, the reference is a great resource, but requires some experience and can be a bit intimidating or esoteric. Additionally, Boost.Python does not provide convenience functions for the entire Python/C API, requiring developers to occasionally code directly to the Python/C API.

Here is a complete Boost.Python example with python code noted in the comments:

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

/// @brief dir() support for Boost.Python objects.
boost::python::object dir(boost::python::object object)
{
  namespace python = boost::python;
  python::handle<> handle(PyObject_Dir(object.ptr()));
  return python::object(handle);
}

/// @brief callable() support for Boost.Python objects.
bool callable(boost::python::object object)
{
  return 1 == PyCallable_Check(object.ptr());
}

class base {};

/// @brief Returns list of an object's non-special and non-callable
///        attributes.
boost::python::list enumerate(boost::python::object object)
{
  namespace python = boost::python;
  python::list attributes; // d = []

  typedef python::stl_input_iterator<python::str> iterator_type;
  for (iterator_type name(dir(object)), end; // for attr in dir(self):
       name != end; ++name)
  {
    if (!name->startswith("__")           // not attr.startswith('__')
        && !callable(object.attr(*name))) // not callable(getattr(self, attr))
      attributes.append(*name);           // d.append(attr)
  }

  return attributes; // return d
}

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::class_<base>("Base")
    .def("Enumerate", &enumerate)
    ;
}

And its usage:

>>> from example import Base
>>> 
>>> class One(Base):
...     hello = "world"
... 
>>> class Two(Base):
...     foo = "bar"
... 
>>> arr = [One(), Two()]
>>> 
>>> arr[0].Enumerate()
['hello']
>>> arr[1].Enumerate()
['foo']

Although Boost.Python does a great job at providing seamless interoperability between Python and C++, when possible, consider writing Python in Python rather than C++. While this is a simple example, the program gains little or nothing being written in C++. On more extensive examples, it can quickly require attention to very minute details, presenting an interesting challenge to maintain a Pythonic feel.

Tanner Sansbury
  • 51,153
  • 9
  • 112
  • 169