¿Cómo SWIG ajusta un mapa en Python?

Estoy usando SWIG 2.0 para crear un contenedor de Python para una biblioteca de C ++. Un método tiene un argumento de tipo “const std :: map &”. SWIG felizmente genera una envoltura para él, pero no puedo descubrir cómo invocar el método. Si paso, por ejemplo, {“a”: “b”} para ese argumento, obtengo un error “NotImplementedError: Número incorrecto o tipo de argumentos para la función sobrecargada”.

Miré el archivo .cxx generado con la esperanza de que se aclarara, pero no fue así. Aquí está el código que procesa ese argumento:

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 const &""'"); } 

Claramente sabe que el argumento existe, y que se supone que es algo que se convierte en un mapa. Pero no puedo entender lo que realmente quiere que pase por ello.

Cuando estás usando una plantilla de C ++ (por ejemplo, std::map ) necesitas crear un alias para él en tu archivo .i para que puedas usarlo en python:

 namespace std { %template(map_string_string) map; } 

Ahora digamos que quieres envolver una función que se vea así:

 void foo(const std::map &arg); 

En el lado de Python, necesitas pasar un map_string_string a foo, no un dict de python. Resulta que puedes convertir fácilmente un dict de python en un mapa haciendo esto:

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

así que si quieres llamar a foo, necesitas hacer esto:

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

Aquí está el código de ejemplo completo que funciona.

 // test.i %module test %include "std_string.i" %include "std_map.i" namespace std { %template(map_string_string) map; } void foo(const std::map &val); %{ #include  #include  #include  using namespace std; void foo(const map &val) { map::const_iterator i = val.begin(); map::const_iterator end = val.end(); while (i != end) { cout << i->first << " : " << i->second << endl; ++i; } } %} 

Y el código de prueba de python:

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

Y mi línea de comando:

 % 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