[C++-sig] Re: Interface slices between python and c++

Neal D. Becker ndbecker2 at verizon.net
Thu Jul 29 22:27:03 CEST 2004


I think I may have answered my own question.  We can make a vector, and also
a vector_slice object.  Some sample code is below.  One thing I still need
to figure out, is I know I need to increment refcnt of vector when creating
vector_slice, but I don't yet know how to do it.

A vector_slice object has usual c++ iterator protocol, so I can pass it to a
generic c++ algorithm without having to write a new wrapper.  (The same
wrapper that works for vector also works for vector_slice.)


Comments?

example:

python
Python 2.3.3 (#1, May  7 2004, 10:31:40) 
[GCC 3.3.3 20040412 (Red Hat Linux 3.3.3-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from vector import *
>>> v=IVec(10)
>>> for i in xrange(0,10):
...   v[i]=i
... 
>>> IVecSliceTimesIntInplace (IVec_slice (v, slice (0,4)), 2)
>>> [e for e in v]
[0, 2, 4, 6, 4, 5, 6, 7, 8, 9]
>>> 

vector.cc:
#include <boost/python/class.hpp>
#include <boost/python/init.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/operators.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/slice.hpp>
#include <string>
#include <vector>
#include <complex>
#include <iostream>
#include <numeric>
#include <iterator>
#include <boost/type_traits.hpp>
#include "mismatch.H"

typedef std::complex<double> Complex;
typedef std::complex<int> ComplexI;

using namespace boost::python;

template<typename in1_cont_t, typename in2_cont_t, typename out_cont_t>
inline void add_vector_wrapper (in1_cont_t in1, in2_cont_t in2, out_cont_t
out) {
  typedef typename boost::remove_reference<in1_cont_t>::type::const_iterator
it1_t;
  typedef typename boost::remove_reference<in2_cont_t>::type::const_iterator
it2_t;
  typedef typename boost::remove_reference<out_cont_t>::type::iterator
it3_t;

  if (in1.size() != in2.size() || in1.size() != out.size())
    throw size_mismatch();
  
  it1_t it1 = in1.begin();
  it2_t it2 = in2.begin();
  it3_t it3 = out.begin();
  for ( ; it1 != in1.end(); it1++, it2++, it3++)
    *it3 = *it1 + *it2;
}

template<typename in1_cont_t, typename scale_t, typename out_cont_t>
inline void times_vector_scalar_wrapper (in1_cont_t in1, scale_t scale,
out_cont_t out) {
  typedef typename boost::remove_reference<in1_cont_t>::type::const_iterator
it1_t;
  typedef typename boost::remove_reference<out_cont_t>::type::iterator
it2_t;

  if (in1.size() != out.size())
    throw size_mismatch();
  
  it1_t it1 = in1.begin();
  it2_t it2 = out.begin();
  for ( ; it1 != in1.end(); it1++, it2++)
    *it2 = *it1 * scale;
}

template<typename in1_cont_t, typename scale_t>
inline void times_vector_scalar_inplace_wrapper (in1_cont_t in1, scale_t
scale) {
  typedef typename boost::remove_reference<in1_cont_t>::type::iterator
it1_t;

  it1_t it1 = in1.begin();
  for ( ; it1 != in1.end(); it1++)
    *it1 *= scale;
}

template<typename T>
struct vector_slice {
  typedef typename std::vector<T>::iterator iterator;
  typedef typename std::vector<T>::const_iterator const_iterator;

  std::vector<T>& v;
  boost::python::slice s;
  vector_slice (std::vector<T>& _v, boost::python::slice _s) :
    v (_v),
    s (_s)
  {}

  iterator begin() { return v.begin() + extract<long>(s.start()); }
  iterator end() { return v.begin() + extract<long>(s.stop()); }
  const_iterator begin() const { return v.begin() +
extract<long>(s.start()); }
  const_iterator end() const { return v.begin() + extract<long>(s.stop()); }

  size_t size() const { return (s.step() == object()) ?
      extract<long>(s.stop()) - extract<long>(s.start()) :
      (extract<long>(s.stop()) -
extract<long>(s.start()))/extract<long>(s.step());
  }
};


BOOST_PYTHON_MODULE(vector)
{    

  class_<std::vector<double> >("DVec")
    .def(init<size_t>())
    .def(init<const std::vector<double>&>())
    .def("size", &std::vector<double>::size)
    .def("resize", (void (std::vector<double>::*)(size_t, const
double&) )&std::vector<double>::resize)
    .def("resize", (void (std::vector<double>::*
(size_t) )&std::vector<double>::resize)
    .def(vector_indexing_suite<std::vector<double> >())
    ;

  class_<std::vector<Complex> >("CVec")
    .def(init<size_t>())
    .def(init<const std::vector<Complex>&>())
    .def("size", &std::vector<Complex>::size)
    .def("resize", (void (std::vector<Complex>::*)(size_t, const
Complex&) )&std::vector<Complex>::resize)
    .def("resize", (void (std::vector<Complex>::*
(size_t) )&std::vector<Complex>::resize)
    .def(vector_indexing_suite<std::vector<Complex>, true >())
    ;
    
  class_<ComplexI >("CInt")
    .def(init<int,int>())
    .def ("real", &ComplexI::real)
    .def ("imag", &ComplexI::imag)
    ;

  class_<std::vector<ComplexI > >("CIntVec")
    .def(init<size_t>())
    .def(init<const std::vector<ComplexI>&>())
    .def("size", &std::vector<ComplexI>::size)
    .def("resize", (void (std::vector<ComplexI>::*)(size_t, const
ComplexI&) )&std::vector<ComplexI>::resize)
    .def("resize", (void (std::vector<ComplexI>::*
(size_t) )&std::vector<ComplexI>::resize)
    .def(vector_indexing_suite<std::vector<ComplexI >, true >())
      ;

  class_<std::vector<int> >("IVec")
    .def(init<size_t>())
    .def(init<const std::vector<int>&>())
    .def("size", &std::vector<int>::size)
    .def("resize", (void (std::vector<int>::*)(size_t, const
int&) )&std::vector<int>::resize)
    .def("resize", (void (std::vector<int>::*
(size_t) )&std::vector<int>::resize)
    .def(vector_indexing_suite<std::vector<int> >()) 
    ;

  class_<vector_slice<int> > ("IVec_slice", init<std::vector<int>&,
boost::python::slice>())
    ;
  def ("AddCVec", &add_vector_wrapper<std::vector<Complex>const&,
std::vector<Complex>const&, std::vector<Complex>&>);
  def ("CVecTimesdouble",
&times_vector_scalar_wrapper<std::vector<Complex>const&, double,
std::vector<Complex>&>);
  def ("CVecTimesComplex",
&times_vector_scalar_wrapper<std::vector<Complex>const&, Complex,
std::vector<Complex>&>);

  def ("IVecSliceTimesInt",
&times_vector_scalar_wrapper<vector_slice<int>const&, int,
std::vector<int>&>);
  def ("IVecSliceTimesIntInplace",
&times_vector_scalar_inplace_wrapper<vector_slice<int>&, int>);
}




More information about the Cplusplus-sig mailing list