SWIG如何对地图进行换行< string,string>在Python? [英] How does SWIG wrap a map<string,string> in Python?
问题描述
我使用SWIG 2.0为C ++库创建了一个Python包装器。一个方法有一个类型为const std :: map&的参数。 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',argumentstd :: map< ; std :: string,std :: string> const&');
}
它清楚地知道参数存在,并且它应该是转换为地图。
当你使用C ++模板时(例如 std :: map< string,string>
),您需要在 .i
文件,以便您可以在python中使用它:
namespace std {
%template(map_string_string)map& string> ;;
}
现在让我们假设你要包装一个如下所示的函数:
void foo(const std :: map< string,string>& arg);
在python端,你需要传递一个map_string_string给foo,而不是python dict。原来,你可以很容易地将一个python dict转换为地图,通过这样做:
map_string_string({'a': 'b'})
所以如果你想调用foo, p>
foo(map_string_string({'a':'b'}))
pre>
这是完整的示例代码。
.i
%模块测试
%includestd_string.i
%includestd_map.i
命名空间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 - >第一<< :<< i - >第二< 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
I'm using SWIG 2.0 to create a Python wrapper for a C++ library. One method has an argument of type "const std::map&". SWIG happily generates a wrapper for it, but I can't figure out how to invoke the method. If I pass, for example, {"a":"b"} for that argument, I get a "NotImplementedError: Wrong number or type of arguments for overloaded function" error.
I looked at the generated .cxx file in the hope it would clarify, but it didn't. Here's the code that processes that argument:
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 &""'"); }
It clearly knows that argument exists, and that it's supposed to be something that gets converted to a map. But I can't figure out what it actually wants me to pass for it.
解决方案When you're using a C++ template (e.g. a
std::map<string, string>
) you need to create an alias for it in your.i
file so you can use it in python:namespace std { %template(map_string_string) map<string, string>; }
Now let's say you want to wrap a function that looks like this:
void foo(const std::map<string, string> &arg);
On the python side, you need to pass a map_string_string to foo, not a python dict. It turns out that you can easily convert a python dict to a map though by doing this:
map_string_string({ 'a' : 'b' })
so if you want to call foo, you need to do this:
foo(map_string_string({ 'a' : 'b' }))
Here's full example code that works.
// 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; } } %}
And the python test code:
#run_test.py import test x = test.map_string_string({ 'a' : 'b', 'c' : 'd' }) test.foo(x)
And my command line:
% 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
这篇关于SWIG如何对地图进行换行< string,string>在Python?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!