[C++-sig] Re: regarding your post entitled " Numeric--factory function" onBoost.Python

Li Dongfeng ldfwyn at 163.com
Mon Nov 1 16:41:00 CET 2004


Hi Faheem,

>   boost::python::numeric::array arr(dim1,dim2);
--------------------------------------^^^^^^^^^
The problem with you code is the array constructor function usage.
That function cannot be called with two integers. See the numarray
(or Numeric) docs for correct usage.

   I tested some solution but cannot reach an elegant one.
An elegant solution should use the numarray(or Numeric) API
directly to access the array contents in C++.
But I have only got a make-shift solution: use the boost::python
indexing suite. After you have used the indexing suite to map C++ vector
to Python sequence type, you can use a C++ vector as a python sequence
in C++ to initialize a numarray.array.

  To map a C++ std::vector<double> to a Python sequence type named
``DoubleVec'', just make this boost.python extension:

------------------------
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/numeric.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <vector>
BOOST_PYTHON_MODULE(_numpyext)
{
  class_<std::vector<double> >("DoubleVec")
    .def(vector_indexing_suite<std::vector<double> >());
}
---------------
	
Then in a C++ extension module, use:

---------------
// std::vector conversion to numarray.array
numeric::array vec2array_double(std::vector<double> x){
  return numeric::array(x, "Float64");
}
BOOST_PYTHON_MODULE(_numpyext)
{
  def("_cppvec2array", &vec2array_double);
}
---------------

this really works, the ``x'' in the numeric::array function call
is recognized by the numarray module constructor function ``array''
as a python sequence of type ``DoubleVec''. 
This function is meant to return a array
in python, so in python we can wrap this function up:

-------------------
from _numpyext import _cppvec2array
def cpp2nar(x, shape=None):
    """Convert a C++ <std>vector to a numarray.array.

    If shp is provided then reshape."""
    xar = _cppvec2array(x)
    if shape is not None:
        xar.setshape(shape)
    return xar
def nar2cpp(x, totype=None):
    """Convert a numarray.array to a 1D C++ std::vector.

    xar should be a double type numarray.array
    """
    xv = DoubleVec()
    xv[:] = x.flat
    xv.shape = x.shape
    ## C++ vector may not have a shape attribute,
    ## but we attach it in python.
    ## In C++ although we only use the data as one-dim,
    ## but when converting back to python we can
    ## use the shape infomation.
    ## return value is a C++ vector
    return xv
--------------------------
We also give a conversion utility to convert numarray.array to C++ vector.

Below is a simple test with C++ extension and python wrapper:
----------------------------
// A test that vector indexing works.
std::vector<double> test_log(std::vector<double>& x){
  std::vector<double>::iterator it;
  for(it = x.begin(); it < x.end(); it++)
    *it = log(*it);

  return x;
}
BOOST_PYTHON_MODULE(_testnum)
{
  def("test_log", test_log);
}
---------------------

--------------------
def test():
    x = array([1, 4, 10.5, 100.0], shape=(2,2), type="Float64")
    print x

    xx = nar2cpp(x, totype="Float64")  ## converted to C++ vector
    yy = test_log(xx)     ## done in C++ vector
    y = cpp2nar(yy, shape=x.shape)   ## back to numarray.array

    print y
    return
----------------------------

These code are not complete, they are simplified.
The includes and imports are omitted.  You should
modify as you need. I have not use the module
in production use. I can send you the comple code
files if you like.



Cheers,			
			 
        Li Dongfeng
        ldfwyn at 163.com
          2004-11-01
   

======= 2004-10-30 01:55:00 =======

>Dear Li Dongfeng,
>
>I saw your post on 
>http://mail.python.org/pipermail/c++-sig/2004-August/007857.html I'm 
>trying to do very similar things. Did you meet with any success with your 
>efforts? In particular, I've had difficulty in creating a numeric array in 
>C++ and passing it back to python. I get the impression that these factory 
>functions have something to do with it, but I am not clear. Are these 
>supposed to be used as constructors for arrays? Can you provide an 
>example?
>
>A function like the following compiles without problems, but bombs when I 
>try to use it. Can you help me?
>
>Thanks in advance.                                           Faheem Mitha.
>
>****************************************************************************
>// Convert (C++) numeric matrix to (Python) Numarray numeric array.
>boost::python::object cppmat2pynumarr(Array2D<double> A)
>{
>   int i, j;
>   int dim1 = A.dim1();
>   int dim2 = A.dim2();
>
>   boost::python::numeric::array arr(dim1,dim2);
>   for(i=0; i<dim1; i++)
>     for(j=0; j<dim2; j++)
>       arr[make_tuple(i,j)] = A[i][j];
>   return arr;
>}








More information about the Cplusplus-sig mailing list