2012-01-23 61 views
0

好的,我已經提出了2個關於我的問題的問題,儘管答覆確實有幫助,但我無法爲我的問題找到最佳解決方案。現在讓我解釋我的主要目標/問題。在不使用std_vector.i的情況下實現對std :: vector的支持

由於一些約束我不能在我的大口接口使用std_vector.i,但我需要在Python使用的C++對象(串的矢量的矢量)vector<vector<string>>。我實現了一個解決方案,我將全部的vector<vector<string> >到Python「列表的列表」,其中我做下面的轉換:使用PyString_FromString() 每個vector<string>到Python列表L1,L2,L3,L4每個C++字符串 到Python字符串... ,最後vector<vector<string> >爲包含l1,l2,l3,l4 ..作爲元素的Python List。

雖然,上述解決方案工作正常,我可以在Python中訪問字符串值,但這種解決方案對我來說看起來並不理想。

我更喜歡一個類(不使用std_vector.i),它的對象我可以作爲函數參數傳遞,以填充值和函數返回後,我應該能夠使用ob[0][0]等訪問值。在這我將不得不只爲每個訪問的值在__getitem__中進行一次轉換(C++字符串爲python字符串)。但我不知道如何在Python中定義代表vector<vector<string> >的類,而不使用%template

+0

它是矢量<矢量>。我寫的問題,但由於一些未知錯誤,它顯示矢量>代替矢量<矢量>。 – Saurabh

+0

我這裏不明白的問題 - 你想換一個'的std :: VECTOR'不使用已經提供的接口。你也可以說你已經編寫了代碼'vector >'列表。你能用一個最簡單的例子來解釋你想要包裝什麼,以及爲什麼這些都不明智? – Flexo

+0

好吧,我不使用已經提供的接口,即std_vector.i,因爲它不是在我的組織中可用的(我們使用我們自己的編譯工具和庫,因此我們不能使用std_vector.i)。目前,我做這樣的事情: %採用矢量<矢量> * OUTPUT {矢量<矢量> *結果}; 類型映射(在,numinputs = 0)矢量<矢量> * OUTPUT(矢量<矢量> T){ 1 $ = T; ($ argout,fragment =「t_output_helper」)vector > * OUTPUT {result} $ result = t_output_helper($ result,my_function_to_convert_vectorToList($ 1)); } – Saurabh

回答

1

我已經將std::vector<std::vector<std::string > >的一個最小包裝的例子放在一起,它不包含任何額外的SWIG文件(例如std_vector.i和std_string.i)。

我也把一個小的頭文件來測試我的實現有:

#include <vector> 
#include <string> 
#include <algorithm> 
#include <iterator> 
#include <iostream> 

inline void print_vec(const std::vector<std::string>& v) { 
    std::copy(v.begin(),v.end(), std::ostream_iterator<std::string>(std::cout, "\n")); 
} 

inline void print_vec_vec(const std::vector<std::vector<std::string> >& v) { 
    std::for_each(v.begin(),v.end(),print_vec); 
} 

std::vector<std::vector<std::string> > make() { 
    static std::vector<std::string> test1; 
    static std::vector<std::string> test2; 

    static std::vector<std::vector<std::string> > ret; 
    test1.push_back("hello"); 
    test2.push_back("world"); 
    test2.push_back("another"); 
    ret.push_back(test1); 
    ret.push_back(test2); 
    return ret; 
} 

這是我能想到的,最小的實施有效地行使生成的接口。

我寫的SWIG接口提供了一個std::vector的骨架定義 - 這足以說服SWIG實際包裝這個東西。我們還擴展了它,針對我們關心的兩種情況,提供了__getitem__的實現,這是您希望能夠使用的obj[x][y]語法的最低要求。

%module Test 

%{ 
#include "test.hh" 
%} 

namespace std { 
template <typename T> 
class vector { 
}; 
} 

%extend std::vector<std::vector<std::string> > { 
    std::vector<std::string> __getitem__(unsigned i) throw(std::out_of_range) { 
    return $self->at(i); 
    } 
} 

%extend std::vector<std::string> { 
    const char * __getitem__(unsigned i) throw(std::out_of_range) { 
    return $self->at(i).c_str(); 
    } 
} 

%template (VecString) std::vector<std::string>; 
%template (VecVecString) std::vector<std::vector<std::string> >; 

%include "test.hh" 

有一個竅門那裏c_str()以避免包括std_string.i。該接口允許我做這樣的事情在Python:

Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24) 
[GCC 4.5.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import Test 
>>> t=Test.make() 
>>> print t[0][0] 
hello 
>>> 

它目前不會提高正確類型的Python異常的__getitem__。你可以用%include "exception.i"%exception這樣做,並在$action附近編寫自己的try/catch

您可能還想提供一個類似的實現__setitem__以使其有用。

這可能不會比std_vector.i更快,或者直接轉換爲Python列表的home brew類型映射。總的來說,雖然我認爲不這樣做是一個好主意 - 使用現有的std_vector.i實現而不是重新創建輪子似乎更符合邏輯。

相關問題