【问题标题】:Boost.Python: Fill in a passed in buffer in PythonBoost.Python:在 Python 中填充传入的缓冲区
【发布时间】:2012-05-11 07:27:43
【问题描述】:

我想知道是否可以在 Python 中填充缓冲区(具有以下条件),如果可以,如何填充?

我有一个 C++ 缓冲区,需要用 Python 填充。缓冲区的地址是通过GetAddress 方法获得的,该方法返回一个指向缓冲区地址的void 指针

#include <boost/smart_ptr/shared_ptr.hpp>
class Foo
{
public:
    Foo(const unsigned int length)
    {
        m_buffer = boost::shared_ptr< unsigned char >( new unsigned char[ length ] );
    }

    ~Foo(){}

    void* GetAddress( ) const
    {
        // cast for the sake of this question
        return reinterpret_cast< void* >( m_buffer.get() );
    }

private:
    boost::shared_ptr< unsigned char > m_buffer;
    Foo();
    Foo(const Foo&);
};

使用 Py++,我可以生成 Boost.Python 包装器以将类导出到 Python,如下所示:

#include "boost/python.hpp"
#include "foo.hpp"

namespace bp = boost::python;

BOOST_PYTHON_MODULE(MyWrapper){
    { //::Foo
        typedef bp::class_< Foo, boost::noncopyable > Foo_exposer_t;
        Foo_exposer_t Foo_exposer = Foo_exposer_t( "Foo", bp::init< unsigned int >(( bp::arg("length") )) );
        bp::scope Foo_scope( Foo_exposer );
        bp::implicitly_convertible< unsigned int const, Foo >();
        { //::Foo::GetAddress

            typedef void * ( ::Foo::*GetAddress_function_type )(  ) const;

            Foo_exposer.def( 
                "GetAddress"
                , GetAddress_function_type( &::Foo::GetAddress )
                , bp::return_value_policy< bp::return_opaque_pointer >() );

        }
    }
}

在 Python 中,GetAddress 的输出是指向内存地址的 void *:

>>> import MyWrapper
>>> foo = MyWrapper.Foo(100)
>>> address = foo.GetAddress()
>>> print address
<void * object at 0x01E200B0>
>>>

问题是 Python 不允许我对 void * 地址对象做任何事情。如果我尝试访问缓冲区中的第二个元素,则以下操作均无效:

>>> address + 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'void *' and 'int'
>>> address[1]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'void *' object is unsubscriptable
>>>

环境:Visual Studio 2008、Boost 1.44、gcc-xml 0.9.0、py++ 1.0.0、pygccxml 1.1.0、Python 2.6.6

【问题讨论】:

  • 那么...您的问题是什么?什么没有按预期工作?你不知道该怎么做,到底是什么?
  • 问题是我可以将缓冲区的地址作为空指针获取,但我不能用它做任何事情。例如,它不支持迭代和赋值。总而言之,好点!我会编辑我的问题..
  • 那么你在寻找什么样的填充缓冲区的接口呢?索引?将其视为流?您是否查看过现有的课程,例如bufferStringIO 等?缓冲区填满后,您将如何处理?
  • 我收到了问题末尾发布的错误
  • 我看过 bufferStringIO 但不知道如何将 void 指针对象传递给它们。

标签: python buffer boost-python void-pointers py++


【解决方案1】:

Python 并不真正处理指针。您可以将其导出为不透明的 cookie,但您永远不能对它任何操作(除非将其传回 c++)。

在你的情况下,我会做的是扭转它。与其返回指向 python 的指针,不如在 c++ 中使用一个从 python 获取“缓冲区”的函数。

namespace bp = boost::python
void FillBuffer(Foo& this, bp::list buff)
{
    unsigned char* addr = reinterpret_cast< unsigned char* >( this.GetAddress() );
    for(int i = 0; i < bp::len(buff); i++)
        addr[i] = bp::extract< unsigned char >( buff[i] );
}

Foo_exposer.def("FillBuffer", &FillBuffer);

现在您可以传递一个列表 in 来填充缓冲区。您可以创建一个类似的函数来将缓冲区填充到列表中并将其返回 python。当然,您会希望对缓冲区溢出等问题更加小心,但这应该给您正确的想法。

【讨论】:

  • 谢谢!我试过了,它有效。如果能够在 Python 端做到这一点,那就太好了。
  • 感谢您修复我的代码。我离开了我的主盒子,跳过了编译它。
猜你喜欢
  • 2012-02-04
  • 1970-01-01
  • 2011-02-20
  • 2018-02-07
  • 1970-01-01
  • 2013-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多