[C++-sig] to_python part two

Robert Andre randre at pppl.gov
Wed Feb 27 17:53:48 CET 2002


Lets see if this makes more sense.  I am including only the
relevant parts of the code below. 

I have a C++ class which is meant to act like an array and 
defined as follows,

------------- uarray.h ------------
typedef valarray<size_t> Shape ;     // set of indices, e.g. (3,5)

class uarray {
public:
  uarray(const Shape&) ;             // construction

  double operator[](const Shape&) ;  // return a single double
  uarray operator[](size_t) ;        // return a slice
}
-----------------------------------

and I have a file for mapping my Shape class to python tuples,

---------- shape.h ------------
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
 
BOOST_PYTHON_DECL PyObject* to_python(const Shape&) ;
BOOST_PYTHON_DECL Shape from_python(PyObject*, boost::python::type<Shape>) ;
Shape from_python(PyObject*, boost::python::type<const Shape&>) ;
 
BOOST_PYTHON_END_CONVERSION_NAMESPACE
-------------------------------

and a separate wrapping code for boost,

------------- arraymod.cc -----------------
BOOST_PYTHON_MODULE_INIT(arraymod) {
  try {
    python::module_builder arraymod("arraymod") ;
 
    // --- class builders ---
    python::class_builder<uarray> uarray_class(arraymod, "uarray") ;

    uarray_class.def((double (uarray::*)(const Shape&) const) &uarray::operator[], "__getitem__") ;

  } catch(...) {
    //    python::handle_exception() ;
    throw ;
  } ;
}
-------------------------------------------

All of this works great so that I can do the following

  >> u = uarray((5,10))
  >> print u[(2,3)]
  0.0

HOWEVER, what I can't do now but I would like to be able to do 
is the following in python

  >> u = uarray((5,10))
  >> print u[(2,3)]       # same as before
  0.0
  >> print u[3][2]        # <--NEW-- slice first then return [2] of slice
  0.0

where u[3] returns a rank one uarray using the  uarray::operator[](size_t)
method and u[3][2] returns the double value.  This requires that
the method uarray::operator[](size_t) return a double for rank 1 arrays
or a uarray if the rank>1. C++ doesn't do multiple return types for
the same argument type but python does so my solution (I hope) is to 
create a helper function which deals directly with the python argument
and return types,

-------------- uarray_helper.cc ------------------
# include <boost/python/detail/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/detail/none.hpp>
# include <boost/python/detail/signatures.hpp>
# include <boost/python/detail/extension_class.hpp>
# include <boost/smart_ptr.hpp>
# include <boost/python/errors.hpp>

PyObject* uarray_getitem(const uarray& u, PyObject* p) {

  PyObject* result = 0 ;
  ... code ...

  uarray uslice = u[k] ;       // find slice, int k extracted from p
  result = to_python(uslice) ; // <-- COMPILER COMPLAINS -- convert uarray to PyObject* 

  ... more code ...
  return result ;
} ; 

--------------------------------------------------

and wrap it instead of operator[]()

------------- arraymod.cc -----------------
BOOST_PYTHON_MODULE_INIT(arraymod) {
  try {
    python::module_builder arraymod("arraymod") ;
 
    // --- class builders ---
    python::class_builder<uarray> uarray_class(arraymod,     "uarray") ;

    uarray_class.def(&uarray_helper, "__getitem__") ;  // <----- CHANGE ----

  } catch(...) {
    //    python::handle_exception() ;
    throw ;
  } ;
}
-------------------------------------------


My problem is in compiling uarray_helper.cc.  to_python(uarray) is known from
extension_class.hpp but it complains about py_extension_class_converters.  I
am unfortunately at my limit of C++ knowledge.

g++ -I/usr/local/include/python2.2 -I/usr/local/include -c  -g -ftemplate-depth-32 -o uarray_helper.o uarray_helper.cc
/usr/local/include/boost/python/detail/extension_class.hpp: In function
   `PyObject* boost::python::to_python(const T&) [with T = uarray]':
uarray_helper.cc:41:   instantiated from here
/usr/local/include/boost/python/detail/extension_class.hpp:393: `py_extension_class_converters'
   undeclared (first use this function)
/usr/local/include/boost/python/detail/extension_class.hpp:393: (Each
   undeclared identifier is reported only once for each function it appears
   in.)

Dave, thanks for any help you can provide.  Boost python is really slick and
I am hoping to be able to use it here at the princeton plasma physics lab.

rob andre




More information about the Cplusplus-sig mailing list