如何使用boost :: python从派生类中获取所有类的attr名称?

时间:2013-09-17 09:02:44

标签: c++ python boost python-2.7 boost-python

我想实现并使用一些类Base。在Python中就是这样:

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()

但我想使用Base在C ++中实现boost::python类。

我搜索了很多,但没有发现任何东西。看起来与boost::python::wrapper相关的内容。

有人能指出我如何做到的方式吗?

1 个答案:

答案 0 :(得分:2)

如果您不熟悉Boost.Python,那么tutorial是一个很好的起点。除此之外,reference是一个很好的资源,但需要一些经验,可能有点令人生畏或深奥。另外,Boost.Python不为整个Python/C API提供便利功能,要求开发人员偶尔直接编写Python / C API代码。

这是一个完整的Boost.Python示例,其中包含注释中的python代码:

#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)
    ;
}

及其用法:

>>> 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']

尽管Boost.Python在提供Python和C ++之间的无缝互操作性方面做得很好,但是如果可能的话,考虑用Python而不是C ++编写Python。虽然这是一个简单的例子,但程序很少或根本没有用C ++编写。在更广泛的例子中,它可以很快地需要关注非常微小的细节,为维持Pythonic的感觉提出了一个有趣的挑战。