Hi all,
I hope this is the correct place to post my question. I'd like python
to interface with c++ code that makes heavy use of Blitz++ arrays.
After a day's hacking I appear to have a simple working solution which I
am attaching. (It uses Boost.Python and CMake.)
However I believe this solution won't work if the blitz array is not
laid out contiguously in memory. I also haven't really thought about
reference counting issues (although the example seems to work). I
imagine that those sorts of issues will lead me to call the more
complicated:
PyArray_New(...)
or:
PyArray_NewFromDescr(...)
instead of the PyArray_SimpleNewFromData(...) that I currently use.
However I couldn't figure out some of the extra arguments from the API
documentation.
Can someone point out all the things that will break when this code
actually gets used in the real world (and maybe even how to avoid them)?
Thanks for your time!
-Philip.
cmake_minimum_required(VERSION 2.6)
find_package(PythonInterp)
find_package(PythonLibs)
find_package(Boost COMPONENTS python)
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
INCLUDE_DIRECTORIES (${Boost_INCLUDE_DIR})
ADD_DEFINITIONS(-Wall -O2)
add_library (simple SHARED simple.cpp)
SET_TARGET_PROPERTIES(simple
PROPERTIES
SOVERSION 0.0.1
VERSION 0.0.1
)
TARGET_LINK_LIBRARIES (simple ${PYTHON_LIBRARIES})
TARGET_LINK_LIBRARIES (simple ${Boost_LIBRARIES})
#include <boost/python.hpp>
#include <numpy/arrayobject.h>
#include <blitz/array.h>
using namespace boost::python;
using namespace blitz;
template<class T, int N>
Array<T,N> py_to_blitz(object arr)
{
PyArrayObject* arr_obj = (PyArrayObject*) arr.ptr();
TinyVector<int,N> shape(0);
TinyVector<int,N> strides(0);
for (int i = 0; i < N; i++)
{
shape[i] = arr_obj->dimensions[i];
strides[i] = arr_obj->strides[i]/sizeof(T);
}
return Array<T,N>((T*) arr_obj->data,shape,strides,neverDeleteData);
}
template<class T, int TYPENUM, int N>
PyObject* blitz_to_py(Array<T,N> arr)
{
import_array1((PyObject*)NULL);
npy_intp dims[N], strides[N];
for (int n=0;n<N; n++)
{
dims[n] = arr.extent(n);
strides[n] = arr.stride(n);//*sizeof(T);//???
}
PyObject* ans = PyArray_SimpleNewFromData(N, dims, TYPENUM, arr.data());//This doesn't actually use strides!?!
// // When/how would I use these calls??
// PyObject* ans = PyArray_New(PyTypeObject* subtype, N, dims, TYPENUM, strides, arr.data(), sizeof(T), NPY_WRITEABLE, PyObject* obj);
// PyObject* ans = PyArray_NewFromDescr(PyTypeObject* subtype, PyArray_Descr* descr, N, &dims[0], &strides[0], arr.data(), NPY_WRITEABLE, PyObject* obj);
return ans;
}
void print(Array<bool,1>& b)
{
for (int n=0; n<b.size(); n++)
std::cout << b(n)<<'\t';
std::cout << endl;
}
BOOST_PYTHON_MODULE(libsimple)
{
class_<Array<bool,1> >("BoolVec");
def("toBoolVec", &py_to_blitz<bool,1>);
def("fromBoolVec",&blitz_to_py<bool, PyArray_BOOL, 1>);
def("cout",&print);
}
from pylab import *
from libsimple import *
py = rand(10)<0.5
print py
c = toBoolVec(py)
cout(c)
py2 = fromBoolVec(c)
del(c)
print py2
_______________________________________________
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion