Я работаю в системе Computer Vision с OpenCV на C ++. Я написал небольшой графический интерфейс для него, используя Boost :: Python и PyQT4. Поскольку я не хочу вводить QT в проект C ++, мне нужен способ представить Mat :: data (член без знака char *) Python, чтобы создать там QImage.
Сначала я попробовал это так:
class_<cv::Mat>("Mat", init<>())
.add_property("data_", make_getter(&Mat::data))
но потом я получил это в Python: «Ошибка типа: не найден конвертер to_python (по значению) для типа C ++: unsigned char *»
Я не смог написать конвертер для него, потому что 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 ++ освобождает его.