2011-03-10 70 views
9

我遇到類似的問題Wrap std::vector of std::vectors, C++ SWIG Python - 但它不僅僅是簡單的C++解析。我在我的C++代碼SWIG包裝矢量向量(C++到Python) - 如何將內部向量識別爲代理對象?

namespace ns { 
    typedef unsigned long long uint64_t; 
    typedef std::vector<uint64_t> Vector; 
    typedef std::vector<Vector> VectorOfVectors; 

    class MyClass { 
     /// ... 

     /// Returns a reference to the internal vector allocated in C++ land 
     const VectorOfVectors &GetVectors() const; 
    }; 
} 

而在夜風包裝

%module myswig  
// ... 
%template(Uint64V) std::vector<ns::uint64_t>; 
%template(VUint64V) std::vector<std::vector<ns::uint64_t> >; 

所以包裝工作正常,包括類以下的,我可以檢索向量的類的載體OK:

import myswig 
m = myswig.MyClass() 
v = m.GetVectors() 
print v 

這給了我:

<myswig.VUint64V; proxy of <Swig Object of type 'std::vector< std::vector< ns::uint64_t,std::allocator<ns::uint64_t> > > *' at 0x994a050> > 

但是,如果我訪問向量中的元素,我不會得到一個代理是一個myswig.Uint64V - 這是我的問題。

x = v[0] 
print x 

我倒是希望得到的是:

<myswig.Uint64V; proxy of <Swig Object of type 'std::vector< ns::uint64_t, std::allocator<ns::uint64_t> > *' at 0x994a080> > 

相反,我越來越:

(<Swig Object of type 'ns::uint64_t *' at 0x994a080>, <Swig Object of type 'ns::uint64_t *' at 0x994a098>) 

也就是說,索引向量的向量是給我一個2條目元組,而不是我需要的向量類的代理(以便訪問內部向量與訪問其他向量一樣簡單)。

我也得到警告:

swig/python detected a memory leak of type 'ns::uint64_t *', no destructor found. 

原因當然沒有這種類型定義的析構函數。

任何想法?

回答

10

我與我的一位同事一起工作過,我們設法想出了一些解決方案。

首先,在SWIG .i文件,它定義了這個預處理器變量是很重要的:

%{ 
# define SWIG_PYTHON_EXTRA_NATIVE_CONTAINERS 
%} 

然後,以確保引用的方法,如前(返回),返回() ,運營商[]等實際上映射到正確的代理類型內部向量,以下typemaps幫助:

// In pop() 
%typemap(out) std::vector<std::vector<ns::uint64_t> >::value_type { 
$result = SWIG_NewPointerObj(SWIG_as_voidptr(&$1), $descriptor(std::vector<ns::uint64_t>), 0 | 0); 
} 

// In front(), back(), __getitem__() 
%typemap(out) std::vector<std::vector<ns::uint64_t> >::value_type & { 
    $result = SWIG_NewPointerObj(SWIG_as_voidptr($1), $descriptor(std::vector<ns::uint64_t>), 0 | 0); 
} 

我們還發現,如果你想要的NS :: uint64_t中來,只要一個python來處理變量(相當於一個C無符號long long),然後再進一步typemap需要確保使用值和引用的向量方法將使用64位整數值。

// In __getitem__() 
%typemap(out) ns::uint64_t { 
    $result = PyLong_FromUnsignedLongLong($1); 
} 
// Not used (but probably useful to have, just in case) 
%typemap(in) ns::uint64_t { 
    $1 = PyLong_AsUnsignedLongLong($input); 
} 
// In pop() 
%typemap(out) std::vector<ns::uint64_t>::value_type { 
    $result = PyLong_FromUnsignedLongLong($1); 
} 
// In __getitem__(), front(), back() 
%typemap(out) std::vector<ns::uint64_t>::value_type & { 
    $result = PyLong_FromUnsignedLongLong(*$1); 
} 
// In __setitem__(), append(), new Uint64Vector, push_back(), assign(), resize(), insert() 
// This allows a python long literal number to be used as a parameter to the above methods. 
// Note the use of a local variable declared at the SWIG wrapper function scope, 
// by placing the variable declaration in parentheses() prior to the open brace { 
%typemap(in) std::vector<ns::uint64_t>::value_type & (std::vector<ns::uint64_t>::value_type temp) { 
    temp = PyLong_AsUnsignedLongLong($input); 
    $1 = &temp; 
} 

我希望這個解決方案可以幫助未來的人!

+0

我有const引用和指針和const指針綁定的問題,你能提供更多的信息嗎? – squid 2016-01-08 02:52:28

+0

定義線非常重要......但它同時是......不顯眼的。我想知道你是如何找到它的。 – squid 2016-01-14 04:39:01