2

boost::python を使用して、C 構造体を C++ から numpy 配列として python に渡そうとしています。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 に答える