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

Posted

技术标签:

【中文标题】SWIG 如何在 Python 中包装 map<string,string>?【英文标题】:How does SWIG wrap a map<string,string> in Python? 【发布时间】:2012-01-27 22:58:11 【问题描述】:

我正在使用 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" "', argument " "4"" of type '" "std::map< std::string,std::string > const &""'"); 

它清楚地知道参数存在,并且它应该是转换为地图的东西。但我无法弄清楚它到底想让我为它传递什么。

【问题讨论】:

在你的 swig 文件中明确地包装地图?我认为您需要通过从 python 代码中调用 insert 来创建填充类型的变量。 【参考方案1】:

当您使用 C++ 模板(例如 std::map&lt;string, string&gt;)时,您需要在您的 .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

【讨论】:

看来您甚至不需要在 Python 代码中使用 map_string_string 类型。声明模板后,SWIG 可以自动计算出如何将 dict 转换为它。

以上是关于SWIG 如何在 Python 中包装 map<string,string>?的主要内容,如果未能解决你的问题,请参考以下文章

SWIG python初始化一个指向NULL的指针

在 try catch 中包装所有 swig 生成的方法

模板包装上的 SWIG 错误

在 Swig 中通过 ref 返回动态数组

如何在 SWIG 中为 c++ 创建模板函数?

Swig:如何将 c++ 字符串 const & 类型映射到 python 字符串?