Как выставить необработанные байтовые буферы с Boost::Python?

У меня есть сторонняя библиотека C++, в которой некоторые методы класса используют сырые байтовые буферы. Я не совсем уверен, как с этим справиться в Boost::Python.

Заголовок библиотеки C++ выглядит примерно так:

class CSomeClass
{
  public:
      int load( unsigned char *& pInBufferData, int & iInBufferSize );
      int save( unsigned char *& pOutBufferData, int & iOutBufferSize );
}

Застрял в коде Boost::Python...

class_<CSomeClass>("CSomeClass", init<>())
    .def("load", &CSomeClass::load, (args(/* what do I put here??? */)))
    .def("save", &CSomeClass::save, (args(/* what do I put here??? */)))

Как мне обернуть эти необработанные буферы, чтобы представить их как необработанные строки в Python?

1 ответ

Решение

Вы должны сами написать функции для своих привязок, которые будут возвращать объект Py_buffer из этих данных, что позволяет использовать их только для чтения (используйте PyBuffer_FromMemory) или чтение-запись (использовать PyBuffer_FromReadWriteMemory) ваша предварительно выделенная память C/C++ от Python.

Вот как это будет выглядеть (обратная связь приветствуется):

#include <boost/python.hpp>

using namespace boost::python;

//I'm assuming your buffer data is allocated from CSomeClass::load()
//it should return the allocated size in the second argument
static object csomeclass_load(CSomeClass& self) {
  unsigned char* buffer;
  int size;
  self.load(buffer, size);

  //now you wrap that as buffer
  PyObject* py_buf = PyBuffer_FromReadWriteMemory(buffer, size);
  object retval = object(handle<>(py_buf));
  return retval;
}

static int csomeclass_save(CSomeClass& self, object buffer) {
  PyObject* py_buffer = buffer.ptr();
  if (!PyBuffer_Check(py_buffer)) {
    //raise TypeError using standard boost::python mechanisms
  }

  //you can also write checks here for length, verify the 
  //buffer is memory-contiguous, etc.
  unsigned char* cxx_buf = (unsigned char*)py_buffer.buf;
  int size = (int)py_buffer.len;
  return self.save(cxx_buf, size);
}

Позже, когда вы связываете CSomeClass, используйте статические функции выше вместо методов load а также save:

//I think that you should use boost::python::arg instead of boost::python::args
// -- it gives you better control on the documentation
class_<CSomeClass>("CSomeClass", init<>())
    .def("load", &csomeclass_load, (arg("self")), "doc for load - returns a buffer")
    .def("save", &csomeclass_save, (arg("self"), arg("buffer")), "doc for save - requires a buffer")
    ;

Это будет выглядеть достаточно питонно для меня.

Другие вопросы по тегам