返回向量<pair <int,int>&gt; &安培;从c ++方法到使用swig typemap </pair <int,int>的元组的python列表

时间:2013-11-21 15:43:13

标签: c++ python vector swig

我在尝试使用%typemap(out)包装c ++方法时遇到了很多麻烦,该方法将对对象的常量引用返回到Python元组列表。

我目前有这样的事情:

myclass.h:

#inlcude <vector>
using std::vector;
class MyClass {
private:
    const vector<pair<int,int>> & _myvector;
public:
    MyClass(const vector<pair<int,int>> & myvector );
    const vector<pair<int,int>> & GetMyVector() const;
}

myclass.cpp:

#include "myclass.h"

MyClass::MyClass(const vector<pair<int,int>> & myvector): _myvector(myvector){};

const vector<pair<int,int>> & MyClass::GetMyVector() const {
    return _myvector;
};

myclass.i :(检查ommited)

%module MyClass
%include "std_vector.i"

namespace std {
    %template(vector_pair_int) vector<pair<int,int>>;
}

%typemap(in) (const vector_pair_int &){

    $1 = new vector<pair<int,int>>;
    int size = PyList_Size($input);
    for (int i=0; i<size; i++){
        PyObject *o = PyList_GetItem($input,i);
        PyObject *o1 = PyList_GetItem(o,0);
        PyObject *o2 = PyList_GetItem(o,1);
        $1->push_back(make_pair(PyInt_AsLong(o1),PyInt_AsLong(o2)))
}

}

%typemap(out) (const vector_pair_int &) {
    $result = PyList_New($1.size());
    vector<pair<int,int>>:: const_iterator it;
    int count=0;
    for (it= $1.begin(); it!= $1.end(); ++it){
        PyObject * tup = PyTuple_Pack(2, it->first,it->second);
        PyList_SET_ITEM($result,count,tup);
        count++;
    }
}

好的,所以我不太明白的第一件事是前面的typemap代码(out)没有编译,因为它告诉我$ 1是指向容器而不是引用的指针。当我将$ 1的使用更改为指针时,它会编译,但它不起作用。

其次,在编译的情况下,typemap(in)有效(c ++容器被正确填充),但是当我尝试从python中检索容器时,我得到了垃圾。当我传递给像MyClass([(1,2)])之类的构造函数,然后我使用GetMyVector()它返回一个python列表但是大小为3并且元组上有垃圾......我是什么做错了???

1 个答案:

答案 0 :(得分:8)

此情况不需要自定义类型映射。 SWIG内置了对矢量和对模板的支持,但您必须声明配对模板以及矢量模板:

%module x

%include <std_pair.i>
%include <std_vector.i>
%include <std_string.i>
%template() std::pair<int,int>;
%template(PairVector) std::vector<std::pair<int,int> >;

%{
#include "MyClass.h"
%}

%include "MyClass.h"

示例:

>>> import x
>>> a=x.PairVector(((1,2),(3,4),(5,6)))
>>> b=x.MyClass(a)
>>> b.GetMyVector()
((1, 2), (3, 4), (5, 6))

但请注意,因为您的类被编写为保存对传入向量的引用而不是副本,所以您必须在MyClass的生命周期内保留对它的引用。例如:

>>> del a
>>> b.GetMyVector()
*Undefined Behavior (crash, empty vector, etc.)*