[C++-sig] Bug with custom convertor and stl container?

Will Lee lee.will at gmail.com
Fri Jun 16 19:17:26 CEST 2006


It seems like there's a bug when I use a custom converter (as described in
the FAQ for the custom string) and a wrapped stl container.  If I define a
custom converter and use that type in a std::vector or std::map, I'll get an
"TypeError: No Python class registered for C++" error for that converted
type.

For example, in the following case where I'm converting from type A to a
python integer, std::vector<A> and std::map<int, A> are not working
propertly.  The testMap and testVec unit tests will both fail.  This is
somewhat a showstopper so it would be great if you have any idea on how to
get around this.

Thanks!

ATest.cpp:
#include <boost/python.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

#include <vector>
#include <map>

struct A
{
  int value;
  A() : value(0){};
  A(int v) : value(v) {};
};

bool operator==(const A& v1, const A& v2)
{
  return (v1.value == v2.value);
}

struct B
{
  A a;
};

// Converter from A to python int
struct AToPython
{
  static PyObject* convert(const A& s)
  {
    return boost::python::incref(boost::python::object((int)s.value).ptr());
  }
};

// Conversion from python int to A
struct AFromPython
{
  AFromPython()
  {
    boost::python::converter::registry::push_back(
        &convertible,
        &construct,
        boost::python::type_id< A >());
  }

  static void* convertible(PyObject* obj_ptr)
  {
    if (!PyInt_Check(obj_ptr)) return 0;
    return obj_ptr;
  }

  static void construct(
      PyObject* obj_ptr,
      boost::python::converter::rvalue_from_python_stage1_data* data)
  {
    void* storage = (
        (boost::python::converter::rvalue_from_python_storage< A >*)
        data)->storage.bytes;

    new (storage) A((int)PyInt_AsLong(obj_ptr));
    data->convertible = storage;
  }
};

BOOST_PYTHON_MODULE(atest)
{
  using namespace boost::python;
  to_python_converter< A , AToPython >();
  AFromPython();

  class_<std::vector< A > >("AVec")
    .def(vector_indexing_suite<std::vector<A>, false>())
    ;

  class_< std::map<int, A> >("AMap")
    .def(map_indexing_suite<std::map<int, A>, false >())
    ;

  class_< B >("B")
    .add_property("a", make_getter(&B::a,
return_value_policy<return_by_value>()),
        make_setter(&B::a, return_value_policy<return_by_value>()))
    ;
}



ATest.py:
#!/usr/bin/env python

import unittest
import atest

class ATest(unittest.TestCase):
    def testB(self):
        b = atest.B()
        self.assert_(b.a == 0)
        b.a = 35
        self.assert_(b.a == 35)

    def testMap(self):
        amap = atest.AMap()
        amap[3] = 4
        self.assert_(amap[3] == 4)

    def testVec(self):
        amap = atest.AVec()
        amap.append(4)
        self.assert_(amap[0] == 4)

if __name__ == "__main__":
    unittest.main()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20060616/8bb3dcc0/attachment.htm>


More information about the Cplusplus-sig mailing list