Dear list,<br><br>First, sorry if this is a double-post, I got confused with the subscription. Anyhow, I seek an opinion on good practice.<br><br>I&#39;d like to write simple programs that<br>1) (In Python) allocates numpy array,<br>
2) (In C/C++) fills said numpy array with data.<br><br>To this end I use Boost.Python to compile an extension module. I use the (possibly obsolete?) boost/python/numeric.hpp to allow passing an ndarray to my C-functions. Then I use the numpy C API directly to extract a pointer to the underlying data.<br>
<br>This seemingly works very well, and I can check for correct dimensions and data types, etcetera.<br><br>As documentation is scarce, I ask you if this is an acceptable procedure? Any pitfalls nearby?<br><br>Sample code: C++<br>
<br><span style="font-family: courier new,monospace;">void fill_array(numeric::array&amp; y)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">{</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">const int ndims = 2;</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">// Get pointer to np array</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">PyArrayObject* a = (PyArrayObject*)PyArray_FROM_O(y.ptr());</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">if (a == NULL) {</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">               throw std::exception(&quot;Could not get NP array.&quot;);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">       }</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">if (a-&gt;descr-&gt;elsize != sizeof(double))</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">{</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">throw std::exception(&quot;Must be double ndarray&quot;);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">}</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">if (a-&gt;nd != ndims)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">{</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">throw std::exception(&quot;Wrong dimension on array.&quot;);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">}</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">int rows = *(a-&gt;dimensions);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">int cols = *(a-&gt;dimensions+1);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">double* data = (double*)a-&gt;data;</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">for (int i = 0; i &lt; rows; i++)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">{</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">for (int j = 0; j &lt; cols; j++)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">{</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">*(data + i*cols + j) = really_cool_function(i,j);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">}</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">}</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">}</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">BOOST_PYTHON_MODULE(Practical01)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">{</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">import_array();</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">boost::python::numeric::array::set_module_and_type(&quot;numpy&quot;, &quot;ndarray&quot;);</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">def(&quot;fill_array&quot;,&amp;fill_array);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">}</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">And in python this could be used such as:<br><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">import Practical01</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">import numpy</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">import matplotlib.pyplot as plt</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">import <a href="http://matplotlib.cm">matplotlib.cm</a> as colormaps</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">import time</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">w=500</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">h=500</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">large_array = numpy.ones( (h,w) );</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">t1 = time.time()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">Practical01.fill_array(large_array)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">t2 = time.time()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">print &#39;Horrible calculation took %0.3f ms&#39; % ((t2-t1)*1000.0)</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">plt.imshow(large_array,cmap=colormaps.gray)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">plt.show()</span><br style="font-family: courier new,monospace;">
<br><br>Simplicity is a major factor for me. I don&#39;t want a complete wrapper for ndarrays, I just want to compute and shuffle data to Python for further processing. Letting Python handle allocation and garbage collection also seems like a good idea.<br>
<br>Sincerely,<br>Jonas Einarsson