title: Boost::Python: How do I expose a dynamic non-object array to a PyBuf?
body: <p>I'm working on a Computer Vision system with OpenCV in C++. I wrote a small GUI for it by using Boost::Python and PyQT4. Since I don't want to introduce QT to the C++ project, I need a way to expose Mat::data (an unsigned char * member) to Python in order to create a QImage there.</p>
  
  <p>First I tried it like this:</p>
  
  <pre><code>    class_&lt;cv::Mat&gt;("Mat", init&lt;&gt;())
            .add_property("data_", make_getter(&amp;Mat::data))
  </code></pre>
  
  <p>but then I got this in Python: "TypeError: No to_python (by-value) converter found for C++ type: unsigned char*"</p>
  
  <p>I couldn't write a converter for it because a PyBuf of course needs to know its size.</p>
  
  <p>So my next approach was trying to create a proxy object like this:</p>
  
  <pre><code>struct uchar_array {
    uchar *data;
    size_t size;
    bool copied;
    static const bool debug = true;
  
    // copy from byte array
    uchar_array(uchar *ptr, size_t size, bool copy) {
        this-&gt;size = size;
        this-&gt;copied = copy;
        if(copied) {
            data = new uchar[size];
            memcpy(data, ptr, size);
        } else {
            data = ptr;
        }
        if(debug) LOG_ERR("init %d bytes in @%p, mem @%p", size, this, data);
    }
  
    PyObject *py_ptr() {
        if(debug) LOG_ERR("py_ptr");
        return boost::python::incref(PyBuffer_FromMemory(data, size));
    }
  
    ~uchar_array() {
        if(debug)  LOG_ERR("~uchar_array @%p", this);
        if(copied) {
            if(debug) LOG_ERR("free @%p, mem @%p", this, data);
            delete [] data;
        }
    }
  };
  </code></pre>
  
  <p>And exposing this via a non-member method:</p>
  
  <pre><code>uchar_array *getMatData(Mat &amp;mat) {
    size_t size = mat.rows * mat.cols * mat.elemSize();
    uchar_array *arr = new uchar_array(mat.data, size, true);
    return arr;
  }
  
  
  class_&lt;cv::Mat&gt;("Mat", init&lt;&gt;())
          .def("data", getMatData, with_custodian_and_ward_postcall&lt;1, 0, return_value_policy&lt;manage_new_object&gt; &gt;())
  class_&lt;uchar_array, shared_ptr&lt;uchar_array&gt; &gt;("uchar_array", no_init)
          .def("ptr", &amp;uchar_array::py_ptr);
  </code></pre>
  
  <p>This works and gets me the buffer into Python, but there are two problems with this approach:</p>
  
  <ol>
  <li>I now have to use mat.data().ptr(), it would be nicer to just do mat.data</li>
  <li>When doing mat.data().ptr(), it seems the temporary uchar_array gets destructed immediately after calling ptr(), thus freeing the memory while I still want to use it</li>
  </ol>
  
  <p>I did several experiments with custodian_and_ward and other stuff but got to a point where I stopped to understand this.</p>
  
  <p>So, could anyone please tell me: What's the preferred way to export an unsigned char * to a PyBuf? In two variants, if possible: allocated for Python so should be freed by Python or as internal pointer where C++ frees it.</p>