SWIG如何在Python中包装map <string,string>?</string,string>

时间:2012-01-27 22:58:11

标签: c++ python stl swig

我正在使用SWIG 2.0为C ++库创建Python包装器。一种方法的参数类型为“const std :: map&amp;”。 SWIG很高兴为它生成一个包装器,但我无法弄清楚如何调用该方法。例如,如果我为该参数传递{“a”:“b”},则会出现“NotImplementedError:重载函数的错误数字或参数类型”错误。

我查看生成的.cxx文件,希望它能澄清,但事实并非如此。这是处理该参数的代码:

res4 = SWIG_ConvertPtr(obj3, &argp4, SWIGTYPE_p_std__mapT_std__string_std__string_t,  0  | 0);
if (!SWIG_IsOK(res4)) {
  SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "new_Context" "', argument " "4"" of type '" "std::map< std::string,std::string > const &""'"); 
}

它清楚地知道论证存在,并且它应该被转换为地图。但我无法弄清楚它实际上是希望我传递给它的。

1 个答案:

答案 0 :(得分:19)

当您使用C ++模板(例如std::map<string, string>)时,您需要在.i文件中为其创建别名,以便在python中使用它:

namespace std {
%template(map_string_string) map<string, string>;
}

现在假设你要包装一个如下所示的函数:

void foo(const std::map<string, string> &arg);

在python方面,你需要将map_string_string传递给foo,而不是python dict。事实证明,你可以通过这样做轻松地将python dict转换为地图:

map_string_string({ 'a' : 'b' })

所以如果你想调用foo,你需要这样做:

foo(map_string_string({ 'a' : 'b' }))

这是完整的示例代码。

// test.i
%module test

%include "std_string.i"
%include "std_map.i"

namespace std {
    %template(map_string_string) map<string, string>;
}

void foo(const std::map<std::string, std::string> &val);

%{
#include <iostream>
#include <string>
#include <map>

using namespace std;
void
foo(const map<string, string> &val)
{
    map<string, string>::const_iterator i = val.begin();
    map<string, string>::const_iterator end = val.end();
    while (i != end) {
        cout << i->first << " : " << i->second << endl;
        ++i;
    }
}

%}

和python测试代码:

#run_test.py
import test

x = test.map_string_string({ 'a' : 'b', 'c' : 'd' })
test.foo(x)

我的命令行:

% swig -python -c++ test.i
% g++ -fPIC -shared -I/usr/include/python2.7  -o _test.so test_wrap.cxx
% python run_test.py
a : b
c : d