问题描述
嗨,我正在用SWIG包装C ++,以便在python中使用。为了包装C ++类,我正在使用SWIG。我对类型映射没有好主意,因此我陷入了困境。我有一个包含多个地图的矢量,即。 std :: vector
std::vector<std::map<std::string,int>> WapperCode::wrapper_fuc(){
std::vector<std::map<std::string,int>> outer_vector;
for(int i = 0 ; i < 10 ; i++){
std::map<std::string,int> inner_dict;
inner_dict.insert(std::pair<std::string,int>("first",1));
inner_dict.insert(std::pair<std::string,int>("second",2));
inner_dict.insert(std::pair<std::string,int>("third",3));
outer_vector.insert(outer_vector.begin() + i,inner_dict);
}
return outer_vector;}
我的界面文件包含此
%module wrapper
%{
#include "wrapper.h"
#include <cstdio>
#include <cstdlib>
#include <sys/stat.h>
#include <map>
#include <vector>
#define SWIG_PYTHON_STRICT_BYTE_CHAR // Swig is giving const char while wrapping bytes.
%}
%include "std_vector.i"
%include "std_map.i"
%include "std_pair.i"
%include "std_wstring.i" // Use this for abby wchar dependency
%include "std_string.i" // Get C++ string
%include "./lib/wrapper.h"
%typemap(out) std::vector< std::map< std::string,int,std::less< std::string >,std::allocator< std::pair< std::string const,int > > >,std::allocator< std::map< std::string,int > > > > > &
{
for(int i = 0; i < $1->size(); ++i)
{
int subLength = $1->data()[i].size();
npy_intp dims[] = { subLength };
PyObject* temp = PyArray_SimpleNewFromData(1,dims,NPY_INT,$1->data()[i].data());
$result = SWIG_Python_AppendOutput($result,temp);
}
}
但是当我从python调用此模块时,我得到了:
Out[3]: <Swig Object of type 'std::vector< std::map< std::string,int > > > > > *' at 0x7f4025d8e810>
解决方法
如果您希望返回值是Python字典的实际Python列表,则确实需要类型映射,但是随附的预定义模板可能对您有用。这是一个示例:
test.i:
%module test
%{
#include <vector>
#include <map>
#include <string>
std::vector<std::map<std::string,int>> func() {
std::vector<std::map<std::string,int>> outer_vector;
for(int i = 0 ; i < 10 ; i++){
std::map<std::string,int> inner_dict;
inner_dict.insert(std::pair<std::string,int>("first",1));
inner_dict.insert(std::pair<std::string,int>("second",2));
inner_dict.insert(std::pair<std::string,int>("third",3));
outer_vector.insert(outer_vector.begin() + i,inner_dict);
}
return outer_vector;
}
%}
// These declare the templates
%include <std_vector.i>
%include <std_map.i>
%include <std_string.i>
// You must declare the template instances used so SWIG builds wrappers for them.
// Declare the inner templates before the outer ones.
%template(SiMap) std::map<std::string,int>;
%template(VectorSiMap) std::vector<std::map<std::string,int>>;
// Tell SWIG to wrap the function.
std::vector<std::map<std::string,int>> func();
用例:
>>> import test
>>> d=test.func()
>>> len(d)
10
>>> d
(<test.SiMap; proxy of <Swig Object of type 'std::map< std::string,int > *' at 0x0000028EA68E0B10> >,<test.SiMap; proxy of <Swig Object of type 'std::map< std::string,int > *' at 0x0000028EA712A570> >,int > *' at 0x0000028EA692A750> >,int > *' at 0x0000028EA7110750> >,int > *' at 0x0000028EA7110480> >,int > *' at 0x0000028EA71105A0> >,int > *' at 0x0000028EA71107E0> >,int > *' at 0x0000028EA7110840> >,int > *' at 0x0000028EA7110900> >,int > *' at 0x0000028EA71109F0> >)
它看起来不漂亮,但是可以通过以下方式转换为Python列表/字典:
>>> [dict(x) for x in d]
[{'first': 1,'second': 2,'third': 3},{'first': 1,'third': 3}]
即使没有进行如上的打印,它也仍然可以像列表或字典一样被访问:
>>> d[0]
<test.SiMap; proxy of <Swig Object of type 'std::map< std::string,int > *' at 0x0000028EA68E0B10> >
>>> d[0]['first']
1
>>> d[1]['second']
2
模板中使用的名称也可以用于构建对象以传递给C ++代码:
>>> m = test.SiMap()
>>> m['first'] = 2
>>> v = test.VectorSiMap()
>>> v.push_back(m)
>>> v
<test.VectorSiMap; proxy of <Swig Object of type 'std::vector< std::map< std::string,int,std::less< std::string >,std::allocator< std::pair< std::string const,int > > > > *' at 0x0000028EA71381E0> >
>>> [dict(x) for x in v]
[{'first': 2}]