Как SWIG оборачивает карту <string, string> в Python? - PullRequest
9 голосов
/ 28 января 2012

Я использую SWIG 2.0 для создания оболочки Python для библиотеки C ++.Один метод имеет аргумент типа "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 &""'"); 
}

Он четко знает, что аргумент существует и что он должен быть чем-то, что преобразуется в карту.Но я не могу понять, что он на самом деле хочет, чтобы я смирился с этим.

1 Ответ

19 голосов
/ 28 января 2012

Когда вы используете шаблон 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 в карту, сделав это:

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
...