【问题标题】:How to expose raw byte buffers with Boost::Python?如何使用 Boost::Python 公开原始字节缓冲区?
【发布时间】:2013-04-20 09:31:00
【问题描述】:

我有第三方 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 中将它们作为原始字符串公开?

【问题讨论】:

    标签: python boost boost-python bytebuffer


    【解决方案1】:

    您必须自己在绑定上编写函数,这些函数将从该数据返回 Py_buffer 对象,允许您以只读方式(使用 PyBuffer_FromMemory)或读写(使用 PyBuffer_FromReadWriteMemory)您的从 Python 预分配的 C/C++ 内存。

    这就是它的样子(欢迎反馈):

    #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时,使用上面的静态函数代替loadsave方法:

    //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")
        ;
    

    这对我来说已经够pythonic了。

    【讨论】:

    • py_bufferPyObject* 类型,而您正在调用 .buf 吗?
    • 我认为你是对的,PyBufferObject 之前应该有演员表。这段代码现在已经过时了。新型缓冲区已经存在,可能应该考虑使用它们。
    • 我知道这是一个老问题,但是你能发布一个链接到一些关于那些“新式缓冲区”的信息吗?我似乎找不到任何东西:/
    • 啊,没关系,我想我在这里找到了一些东西:docs.python.org/2/c-api/buffer.html
    • 那是第一句的链接文档。
    猜你喜欢
    • 2014-05-28
    • 2016-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多