Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The Boost::Python API does not allow you to do that directly. You can use the Numpy C API to do it. Getting access to the underlying <code>PyObject*</code> can be done using the <code>ptr()</code> method of <code>boost::python::object</code>. Access to the data can be obtained using <code>PyArray_DATA(PyObject*)</code>.</p> <p>Here's an example that multiplies a 2d Numpy array by a number. I've had some trouble finding out how to compile this on Mac OS (i.e., where the Numpy headers are), so I'll add this here: running</p> <pre><code>import numpy; print numpy.get_include() </code></pre> <p>in Python gives the correct include path. You can for example use that in a cmake Find module (see <a href="http://gitorious.org/avogadro/avogadro/blobs/48cf4f00a03c32ca93856b8ebbed64b549bb7451/cmake/modules/FindNumpy.cmake" rel="nofollow">this</a>, for example; you'll have to set the <code>PYTHON_EXECUTABLE</code> variable yourself).</p> <p><strong>Update:</strong> I modified the code to handle the case in which the input array is not contiguous -- this happens for example whenever you use a slice, as in <code>arr[::2, ::2]</code>. The most straightforward way to handle this is to use <code>PyArray_FROM_OTF</code>; do note, however, that this will make a copy of the array unless the array is already in contiguous form. The advantage of this approach is that it can handle the case in which the input is any kind of nested sequence (e.g., a list of lists).</p> <p>If your array is so big that you would prefer avoiding making copies of it, you can use <code>PyArray_STRIDES</code> to get the stride information that helps you access the data. From <a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.strides.html" rel="nofollow">http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.strides.html</a>,</p> <blockquote> <p>The byte offset of element <code>(i[0], i[1], ..., i[n])</code> in an array <code>a</code> is:</p> <p><code>offset = sum(np.array(i) * a.strides)</code></p> </blockquote> <p>(note that this is the <strong>byte</strong> offset, so you should add it to the result of <code>PyArray_BYTES</code> <strong>before</strong> you cast to final data type; also, this will not help if the array is improperly aligned, or if it has the wrong byte order)</p> <p>Here's the sample code:</p> <pre><code>#include &lt;boost/python.hpp&gt; #include &lt;exception&gt; #include &lt;numpy/arrayobject.h&gt; using namespace boost::python; struct WrongSizeError : public std::exception { const char* what() const throw() { return "Unsupported array size."; } }; struct WrongTypeError : public std::exception { const char* what() const throw() { return "Unsupported array type."; } }; // Boost::Python needs the translators void translate_sz(const WrongSizeError&amp; e) { PyErr_SetString(PyExc_RuntimeError, e.what()); } void translate_ty(const WrongTypeError&amp; e) { PyErr_SetString(PyExc_RuntimeError, e.what()); } // multiply matrix of double (m) by f object multiply(numeric::array m, double f) { PyObject* m_obj = PyArray_FROM_OTF(m.ptr(), NPY_DOUBLE, NPY_IN_ARRAY); if (!m_obj) throw WrongTypeError(); // to avoid memory leaks, let a Boost::Python object manage the array object temp(handle&lt;&gt;(m_obj)); // check that m is a matrix of doubles int k = PyArray_NDIM(m_obj); if (k != 2) throw WrongSizeError(); // get direct access to the array data const double* data = static_cast&lt;const double*&gt;(PyArray_DATA(m_obj)); // make the output array, and get access to its data PyObject* res = PyArray_SimpleNew(2, PyArray_DIMS(m_obj), NPY_DOUBLE); double* res_data = static_cast&lt;double*&gt;(PyArray_DATA(res)); const unsigned size = PyArray_SIZE(m_obj); // number of elements in array for (unsigned i = 0; i &lt; size; ++i) res_data[i] = f*data[i]; return object(handle&lt;&gt;(res)); // go back to using Boost::Python constructs } BOOST_PYTHON_MODULE(test) { // register exception translators register_exception_translator&lt;WrongSizeError&gt;(&amp;translate_sz); register_exception_translator&lt;WrongTypeError&gt;(&amp;translate_ty); // tell Boost::Python under what name the array is known numeric::array::set_module_and_type("numpy", "ndarray"); def("multiply", multiply); // initialize the Numpy C API import_array(); } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload