2012-08-13 76 views
2

我想從C++傳遞一個C結構到python作爲使用boost :: python的numpy數組。我知道有更簡單的方法將C結構傳遞給python,但是我想使用numpy數組的原因是解決方案是反射模型的一部分,所以數據類型需要從字符串中動態生成。傳遞C結構作爲numpy數組使用boost python

我可以序列化將它作爲字符串傳遞給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類,但是我在將它轉換成numpy數組時遇到了問題。的構造是投擲: 「類型錯誤:否to_python(副值)發現C++型轉換器: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++ 

謝謝,

Paul

+0

不知道,但我想你可能想'數字::陣列::廠'。 – ecatmur 2012-08-13 14:23:00

+0

類似的問題:[如何從boost :: python返回numpy.array?](http://stackoverflow.com/q/10701514/222914) – 2012-08-15 09:45:17

回答

2

好的,我已經設法回答我自己的問題。這不是直接的,但現在的工作......再次

#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); 
} 

感謝,

保羅