我正在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,但這種方法有兩個問題:
- 我現在必須使用mat.data()。ptr(),它會更好只是做mat.data
- 在做mat.data()。PTR(),它似乎暫時得到uchar_array調用PTR(),從而釋放內存後立即銷燬,而我還是想用它
我用custodian_and_ward和其他的東西做了幾個實驗,但達到了停止瞭解這一點的地步。
那麼,有誰可以請告訴我:有什麼方法將一個無符號字符*導出到PyBuf?在兩種變體中,如果可能的話:分配給Python,所以應該由Python釋放,或者作爲C++釋放它的內部指針。
使用std :: vector不是一個選項AFAIK,因爲我需要Python的一方(或sip.voidptr)PyBuf。使用更方便的結構是我上面嘗試過的,但我無法獲得內存管理權。它要麼從未遭到破壞,要麼爲時尚早。 – fpw 2012-03-14 08:33:19