C ++ boost.python не может преобразовать const char * в str - PullRequest
0 голосов
/ 17 марта 2019

Я хочу вычислить что-то в C ++ и вернуть результат в python. Это часть кода C ++:

const Mat& flow_map_x, flow_map_y;
std::vector<unchar> encoded_x, encoded_y;

flow_map_x = ...;
flow_map_y = ...;

Mat flow_img_x(flow_map_x.size(), CV_8UC1);
Mat flow_img_y(flow_map_y.size(), CV_8UC1);

encoded_x.resize(flow_img_x.total());
encoded_y.resize(flow_img_y.total());

memcpy(encoded_x.data(), flow_img_x.data, flow_img_x.total());
memcpy(encoded_y.data(), flow_img_y.data, flow_img_y.total());

bp::str tmp = bp::str((const char*) encoded_x.data())

Ошибка при запуске скрипта Python:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte

После отладки я обнаружил, что ошибка исходит из этой строки:

bp::str tmp = bp::str((const char*) encoded_x.data())

Я не очень хорош в C ++. Может кто-нибудь сказать мне, как исправить ошибку? Заранее спасибо!

1 Ответ

0 голосов
/ 17 марта 2019

Вы не можете, потому что encoded_x.data() не UTF-8. Вы, вероятно, хотите bytes для копии необработанных данных:

Использование <a href="https://docs.python.org/3/c-api/structures.html#c.PyObject" rel="nofollow noreferrer">PyObject</a>* <a href="https://docs.python.org/3/c-api/bytes.html#c.PyBytes_FromStringAndSize" rel="nofollow noreferrer">PyBytes_FromStringAndSize</a>(const char *<em>v</em>, Py_ssize_t <em>len</em>). Или вы можете использовать PyByteArray_FromStringAndSize для bytearray с теми же аргументами.

bp::object tmp(bp::handle<>(PyBytes_FromStringAndSize(
    // Data to make `bytes` object from
    reinterpret_cast<const char*>(encoded_x.data()),
    // Amount of data to read
    static_cast<Py_ssize_t>(encoded_x.size())
)));

В этом случае вы можете избавиться от вектора и напрямую использовать flow_img_x.data и flow_img_x.total().


Или memoryview, чтобы не копировать данные, а просто получить доступ к данным std::vector s

Использование PyObject* <a href="https://docs.python.org/3/c-api/memoryview.html#c.PyMemoryView_FromMemory" rel="nofollow noreferrer">PyMemoryView_FromMemory</a>(char *<em>mem</em>, Py_ssize_t <em>size</em>, int <em>flags</em>)

bp::object tmp(bp::handle<>(PyMemoryView_FromMemory(
    reinterpret_cast<char*>(encoded_x.data()),
    static_cast<Py_ssize_t>(encoded_x.size()),
    PyBUF_WRITE  // Or `PyBUF_READ` i if you want a read-only view
)));

(Если бы вектор был константным, вы бы const_cast<char*>(reinterpret_cast<const char*>(encoded_x.data())) использовали бы только PyBUF_READ)

В этом случае вы должны убедиться, что вектор остается живым, но это не создаст ненужную копию.

...