2012-03-13 31 views
1

我正在C++中使用OpenCV開發計算機視覺系統。我使用Boost :: Python和PyQT4爲它編寫了一個小GUI。因爲我不想將QT引入到C++項目中,所以我需要一種將Mat :: data(一個unsigned char *成員)公開給Python的方法,以便在那裏創建一個QImage。Boost :: Python:我如何將一個動態的非對象數組暴露給PyBuf?

首先我想它是這樣的:

class_<cv::Mat>("Mat", init<>()) 
      .add_property("data_", make_getter(&Mat::data)) 

但後來我在Python了這一點: 「類型錯誤:沒有to_python(按值)轉換器找到了C++類型:無符號字符*」

我無法爲它寫一個轉換器,因爲PyBuf當然需要知道它的大小。

所以我的下一個方法試圖創建一個像這樣的代理對象:

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->size = size; 
     this->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; 
     } 
    } 
}; 

,並通過非成員方法公開此:

uchar_array *getMatData(Mat &mat) { 
    size_t size = mat.rows * mat.cols * mat.elemSize(); 
    uchar_array *arr = new uchar_array(mat.data, size, true); 
    return arr; 
} 


class_<cv::Mat>("Mat", init<>()) 
     .def("data", getMatData, with_custodian_and_ward_postcall<1, 0, return_value_policy<manage_new_object> >()) 
class_<uchar_array, shared_ptr<uchar_array> >("uchar_array", no_init) 
     .def("ptr", &uchar_array::py_ptr); 

這工作,並得到我的緩衝區中Python,但這種方法有兩個問題:

  1. 我現在必須使用mat.data()。ptr(),它會更好只是做mat.data
  2. 在做mat.data()。PTR(),它似乎暫時得到uchar_array調用PTR(),從而釋放內存後立即銷燬,而我還是想用它

我用custodian_and_ward和其他的東西做了幾個實驗,但達到了停止瞭解這一點的地步。

那麼,有誰可以請告訴我:有什麼方法將一個無符號字符*導出到PyBuf?在兩種變體中,如果可能的話:分配給Python,所以應該由Python釋放,或者作爲C++釋放它的內部指針。

回答

0

char*緩衝區並不真正的蟒蛇友好。在我的項目中(對性能不敏感),我將使用std :: vector或std :: string,具體取決於它包含的內容。這兩個都很好的蟒蛇友好。

如果您無法更改基礎數據結構,則可以使用add_property和幾個getter和setter函數將數據轉換爲更方便的結構。

+0

使用std :: vector不是一個選項AFAIK,因爲我需要Python的一方(或sip.voidptr)PyBuf。使用更方便的結構是我上面嘗試過的,但我無法獲得內存管理權。它要麼從未遭到破壞,要麼爲時尚早。 – fpw 2012-03-14 08:33:19