2013-05-13 110 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