title: Sending a C++ array to Python and back (Extending C++ with Numpy)
body: <p>I am going to send a <code>c++</code> array to a python function as <code>numpy array</code> and get back another <code>numpy array</code>. After consulting with <code>numpy</code> documentation and some other threads and tweaking the code, finally the code is working but I would like to know if this code is written optimally considering the:</p>
  
  <ul>
  <li>Unnecessary copying of the array between <code>c++</code> and <code>numpy (python)</code>.</li>
  <li>Correct dereferencing of the variables.</li>
  <li>Easy straight-forward approach.</li>
  </ul>
  
  <p>C++ code:</p>
  
  <pre><code>// python_embed.cpp : Defines the entry point for the console application.
  //
  
  #include "stdafx.h"
  
  #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
  #include "Python.h"
  #include "numpy/arrayobject.h"
  #include&lt;iostream&gt;
  
  using namespace std;
  
  int _tmain(int argc, _TCHAR* argv[])
  {
      Py_SetProgramName(argv[0]);
      Py_Initialize();
      import_array()
  
      // Build the 2D array
      PyObject *pArgs, *pReturn, *pModule, *pFunc;
      PyArrayObject *np_ret, *np_arg;
      const int SIZE{ 10 };
      npy_intp dims[2]{SIZE, SIZE};
      const int ND{ 2 };
      long double(*c_arr)[SIZE]{ new long double[SIZE][SIZE] };
      long double* c_out;
      for (int i{}; i &lt; SIZE; i++)
          for (int j{}; j &lt; SIZE; j++)
              c_arr[i][j] = i * SIZE + j;
  
      np_arg = reinterpret_cast&lt;PyArrayObject*&gt;(PyArray_SimpleNewFromData(ND, dims, NPY_LONGDOUBLE, 
          reinterpret_cast&lt;void*&gt;(c_arr)));
  
      // Calling array_tutorial from mymodule
      PyObject *pName = PyUnicode_FromString("mymodule");
      pModule = PyImport_Import(pName);
      Py_DECREF(pName);
      if (!pModule){
          cout &lt;&lt; "mymodule can not be imported" &lt;&lt; endl;
          Py_DECREF(np_arg);
          delete[] c_arr;
          return 1;
      }
      pFunc = PyObject_GetAttrString(pModule, "array_tutorial");
      if (!pFunc || !PyCallable_Check(pFunc)){
          Py_DECREF(pModule);
          Py_XDECREF(pFunc);
          Py_DECREF(np_arg);
          delete[] c_arr;
          cout &lt;&lt; "array_tutorial is null or not callable" &lt;&lt; endl;
          return 1;
      }
      pArgs = PyTuple_New(1);
      PyTuple_SetItem(pArgs, 0, reinterpret_cast&lt;PyObject*&gt;(np_arg));
      pReturn = PyObject_CallObject(pFunc, pArgs);
      np_ret = reinterpret_cast&lt;PyArrayObject*&gt;(pReturn);
      if (PyArray_NDIM(np_ret) != ND - 1){ // row[0] is returned
          cout &lt;&lt; "Function returned with wrong dimension" &lt;&lt; endl;
          Py_DECREF(pFunc);
          Py_DECREF(pModule);
          Py_DECREF(np_arg);
          Py_DECREF(np_ret);
          delete[] c_arr;
          return 1;
      }
      int len{ PyArray_SHAPE(np_ret)[0] };
      c_out = reinterpret_cast&lt;long double*&gt;(PyArray_DATA(np_ret));
      cout &lt;&lt; "Printing output array" &lt;&lt; endl;
      for (int i{}; i &lt; len; i++)
          cout &lt;&lt; c_out[i] &lt;&lt; ' ';
      cout &lt;&lt; endl;
  
      // Finalizing
      Py_DECREF(pFunc);
      Py_DECREF(pModule);
      Py_DECREF(np_arg);
      Py_DECREF(np_ret);
      delete[] c_arr;
      Py_Finalize();
      return 0;
  }
  </code></pre>
  
  <p>In CodeReview, there is a fantastic answer: <a href="https://codereview.stackexchange.com/questions/92266/sending-a-c-array-to-python-numpy-and-back/92353#92353">Link...</a></p>