2

我正在尝试使用 boost::python 将 C 结构从 C++ 传递到 python 作为 numpy 数组。我知道有更简单的方法可以将 C 结构传递给 python,但我想使用 numpy 数组的原因是解决方案是反射模型的一部分,因此需要从字符串动态生成数据类型。

我可以序列化将其作为字符串传递给 python 的结构,并在 python 中调用 numpy.fromstring() ,它成功地将其转换为 numpy 数组。但是,这不是很有效,因为将其转换为字符串会复制数据,而不是通过引用将其传递给 python。

例如:

#include <boost/python.hpp>

using namespace boost::python;

struct MyRecord
{
    uint32_t myInt;
    char myString[4];
    double myDouble;
};

class MyBaseClass
    :   public wrapper<MyBaseClass>
{
public:
    void myCallback(const MyRecord& data)
    {
        object func = get_override("myCallback");
        if (func) {
            std::string dataStr(reinterpret_cast<const char*>(data), sizeof(data));
            func(dataStr, "[('myInt','<u4'),('myString','|S4'),('myDouble','<f8')]");
        }
    }
};

BOOST_PYTHON_MODULE(example1)
{
    class_<MyBaseClass>("MyBaseClass")
        .def("myCallback", &MyBaseClass::myCallback);
}

#!/usr/bin/env python

import numpy
from example1 import MyBaseClass

class MyClass(MyBaseClass):
    def myCallback(self, dataStr, dtypeStr):
        dt = numpy.dtype(eval(dtypeStr))
        data = numpy.fromstring(dataStr, dt)
        print data # This is now a numpy array

我真正想做的是将结构转换为 C++ 中的 numpy 数组,并通过引用直接将其传递给 python。

我已经尝试过 boost::python::numeric::array 类,但是在将 C++ 类型转换为 numpy 数组时遇到了问题。构造函数抛出:“TypeError: No to_python (by-value) converter found for C++ type: MyRecord”

有一些示例代码:

#include <boost/python.hpp>
#include <boost/python/exec.hpp>
#include <boost/python/numeric.hpp>

using namespace boost::python;

struct MyRecord
{
    uint32_t myInt;
    char myString[4];
    double myDouble;
};

class MyBaseClass
    :   public wrapper<MyBaseClass>
{
public:
    void myCallback(const MyRecord& data)
    {
        object func = get_override("myCallback");
        if (func) {
            object dtype = exec("eval(\"[('myInt','<u4'),('myString','|S4'),('myDouble','<f8')]\")");
            func(numeric::array(data, dtype));  // numeric::array throws
        }
    }
};

BOOST_PYTHON_MODULE(example2)
{
    class_<MyBaseClass>("MyBaseClass")
        .def("myCallback", &MyBaseClass::myCallback);
}

#!/usr/bin/env python

import numpy
from example2 import MyBaseClass

class MyClass(MyBaseClass):
    def myCallback(self, data):
        print data # This is a numpy array passed from C++

谢谢,

保罗

4

1 回答 1

3

好的,我已经设法回答了我自己的问题。这不是直截了当的,但它现在有效......

#include <numpy/arrayobject.h>

void MyBaseClass::myCallback(const MyRecord& data)
{
    object func = get_override("myCallback");
    if (func) {
        PyArray_Descr* dtype;
        PyObject* op = Py_BuildValue("[(s,s),(s,s),(s,s)]", "myInt", "<u4", "myString", "|S4", "myDouble", "<f8");
        PyArray_DescrConverter(op, &dtype);
        Py_DECREF(op);
        PyObject* pya = PyArray_FromString(const_cast<char*>(reinterpret_cast<const char*>(&data)), sizeof(data), dtype, 1, NULL);
        // PyObject_Print(pya, stdout, 0);
        numeric::array bpa(static_cast<numeric::array>(handle<>(pya)));
        func(bpa);
    }
}

BOOST_PYTHON_MODULE(example3)
{
    import_array()
    class_<MyBaseClass>("MyBaseClass")
        .def("myCallback", &MyBaseClass::myCallback);
}

再次感谢,

保罗

于 2012-08-16T17:45:41.153 回答