[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",
×_vector_scalar_wrapper<std::vector<Complex>const&, double,
std::vector<Complex>&>);
def ("CVecTimesComplex",
×_vector_scalar_wrapper<std::vector<Complex>const&, Complex,
std::vector<Complex>&>);
def ("IVecSliceTimesInt",
×_vector_scalar_wrapper<vector_slice<int>const&, int,
std::vector<int>&>);
def ("IVecSliceTimesIntInplace",
×_vector_scalar_inplace_wrapper<vector_slice<int>&, int>);
}
More information about the Cplusplus-sig
mailing list