如何将原始指针传递给Boost.Python?

7 投票
2 回答
2718 浏览
提问于 2025-04-17 06:12

我正在尝试使用Boost.Python来包装一个C++函数,这个函数接收一个指针,修改一些数据(比如在Python那边用numpy数组管理的数据),然后返回。请问我该如何让Python的numpy和Boost.Python一起工作,并在函数内部获取原始指针呢?

#include <boost/python.hpp>
namespace
{
  char const *greet(double *p)
  {
    *p = 2.;
    return "hello world";
  }
}
BOOST_PYTHON_MODULE(module)
{
  boost::python::def("greet", &greet);
}

在Python中,当我尝试这样做时,

import numpy as np
a = np.empty([2], dtype=np.double)
raw_ptr = a.data
print cmod.greet(raw_ptr)

我遇到了这个错误,

Boost.Python.ArgumentError: Python argument types in
<...>.module.greet(buffer)
did not match C++ signature:
greet(double*)

2 个回答

0

你可能需要使用numpy的ctypes接口来获取一个指向存储空间的原始指针,然后再创建一个ctypes指针,指向双精度浮点数,以便传递给调用的函数。ndarray.data是一个缓冲区类型,而不是指针。

我对boost.python没有经验,但我猜像下面这样的代码

In [28]: x=np.array([1,2,3,4],dtype=np.double)

In [29]: p=x.ctypes.data_as(ctypes.POINTER(ctypes.c_double))

In [30]: type(p)
Out[30]: <class 'ctypes.LP_c_double'>

如果传递给一个期望指针作为参数的C++函数,应该是可以工作的。

3

有一种方法看起来有效,是Andreas Kloeckner提出的,欢迎大家评论和提供其他建议。greet()函数的修改如下:

char const *greet(boost::python::object obj) {
    PyObject* pobj = obj.ptr();
    Py_buffer pybuf;
    if(PyObject_GetBuffer(pobj, &pybuf, PyBUF_SIMPLE)!=-1)
    {
        void *buf = pybuf.buf;
        double *p = (double*)buf;
        *p = 2.;
        *(p+1) = 3;
        PyBuffer_Release(&pybuf);
    }
    return "hello world";
    }

在Python中只需使用:

print cmod.greet(a)

撰写回答