2013-05-13 61 views
1

我想为我的C++库创建一个python包装。如果自动将std :: vector转换为python列表并相反,这将很酷。 不幸的是,如果我将此代码添加到我的Interface文件中,我仍然在运行时遇到错误。%Python的C++库的类型映射

%typemap(in) std::vector<float> value (std::vector<float> vIn) { 
    int iLen = PySequence_Length($input); 
    for(unsigned int i = 0; i < iLen; i++) { 
     PyObject *o = PySequence_GetItem($input, i); 
     if (PyNumber_Check(o)) { 
      vIn.push_back((float)PyFloat_AsDouble(o)); 
     } 
    } 
    $1 = vIn; 
} 
%typemap(out) std::vector<float> { 
    std::vector<float> vOut = $1; 
    int iLen = vOut.size(); 
    $result = PyList_New(iLen); 
    for(unsigned int i = 0; i < iLen; i++) { 
     double fVal = vOut.at(i); 
     PyObject *o = PyFloat_FromDouble((double) fVal); 
     PyList_SetItem($result, i, o); 
    } 
} 

类的头:

class TrainingSet { 
    private: 
     std::vector<std::vector<float> > m_vInputList; 
     std::vector<std::vector<float> > m_vOutputList; 
    public: 
     void AddInput(const std::vector<float> &vIn); 
    // .. 

Python代码:

trainSet = TrainingSet() 
trainSet.AddInput([0.5, 0.5, 0.5]) 

错误:

File "runSOMNet.py", line 9, in <module> 
trainSet.AddInput([0.5, 0.5, 0.5]) 
File "/home/dgrat/annetgpgpu/build/ANNet/ANPyNetCPU.py", line 674, in AddInput 
def AddInput(self, *args): return _ANPyNetCPU.TrainingSet_AddInput(self, *args) 
NotImplementedError: Wrong number or type of arguments for overloaded function  'TrainingSet_AddInput'. 
Possible C/C++ prototypes are: 
ANN::TrainingSet::AddInput(std::vector< float,std::allocator<float> > const &) 
ANN::TrainingSet::AddInput(float *,unsigned int const &) 

回答

1

如果你要定义手动%typemap S,你还需要一个%typemap(check),是这样的:

%typemap(typecheck) std::vector<float>& { 
    $1 = PySequence_Check($input) ? 1 : 0; 
} 

我相信经验法则是,如果你定义一个%typemap(in),你还应该定义一个%typemap(check) ---否则,生成的代码永远不会到达它的放置位置%typemap(in)

2

std_vector.i库SWIG提供std::vector支持。

http://www.swig.org/Doc2.0/Library.html#Library_stl_cpp_library

你只需要告诉夜风你想要了解的模板实例:

%include "std_vector.i" 

namespace std { 
    %template(FloatVector) vector<float>; 
} 

注意下面的Python代码的工作,但会招致数组复制:

要使用SWIG生成的代理对象构造函数构造列表:
list = myModule.FloatVector() 
for x in range(0, 3): 
    list[x] = x 
myModule.myFunction(list) 
+0

我已经做了这种东西,但这不是我想要做的。我的目标是将Python列表作为函数参数自动转换为这样的std :: vector。或者通过捕获返回值来反过来。问题是,std :: vector无法转换为python列表,没有读取每个值并将其写入新列表。 – dgrat 2013-05-14 07:08:33

+0

@ user1909456这是不可能的。除非PyList支持C++ 11移动语义,否则不能复制数据从PyList构建std :: vector。与AFAICT类似,您不能在不复制数据的情况下从std :: vector构造PyList。但是,如果使用'std_vector.i'来封装一个返回std :: vector的函数,那么在Python中它将返回一个像Python列表一样的对象,而不复制数据。你可以从Python构造一个std :: vector包装器对象,它像_ Python列表一样,并将其传递给你的包装函数而不复制数据。 – Oktalist 2013-05-14 14:33:08