Как передать необработанный указатель в Boost.Python? - PullRequest
7 голосов
/ 13 ноября 2011

Я пытаюсь использовать 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 ]

3 голосов
/ 14 ноября 2011

Один из подходов, предложенный Андреасом Клёкнером, приветствует комментарии и альтернативы.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)
0 голосов
/ 13 ноября 2011

Вам, вероятно, понадобится использовать интерфейс 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 ++, ожидающая указатель в качестве аргумента.

...