2012-01-27 5 views
8

SWIG 2.0を使用して、C++ライブラリのPythonラッパーを作成しています。 1つのメソッドには、 "const std :: map &"という型の引数があります。 SWIGは喜んでそのラッパーを生成しますが、メソッドを呼び出す方法を理解することはできません。たとえば、その引数に{"a": "b"}を渡すと、 "NotImplementedError:関数のオーバーロードされた関数の引数またはタイプが間違っています"というエラーが表示されます。SWIGはどのようにして<string、string>マップをPythonでラップしますか?

私は、生成された.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 &""'"); 
} 

それは明らかに引数が存在することを知って、マップに変換される何かことになっていること:ここでは、その引数を処理するコードです。しかし、私はそれが実際に私がそれを渡すことを望んでいるものを理解できません。

+0

あなたに明示的にマップをラップ?私はあなたがPythonコード内から挿入を呼び出すことによって、データ型の変数を作成する必要があると思います。 – mark

答えて

16

あなたがC++テンプレート(例えばstd::map<string, string>)を使用している場合は、あなたがpythonでそれを使用することができますので、あなたの.iファイルにそれのためのエイリアスを作成する必要があります。

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

今度は、あなたがしたいとしましょうこのようになります機能ラップ:pythonの側で

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

を、あなたは、fooへのmap_string_string、ないPythonの辞書を渡す必要があります。それはあなたが簡単にこれを行うことによって、しかし、マップにPythonの辞書に変換することができていることが判明した:あなたがfooを呼び出したい場合は

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

ので、あなたはこれを実行する必要があります。

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ファイルで

% 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 
+0

これは私にとってはうまくいきません:map_string_string({'a': 'b'})は{'a': 'b'}とまったく同じエラーを生成します。私は生成されたC++のコードをハックして、何が起こっているのかについてより多くの情報を得ることができました。それは私には意味がありません。 dict(またはmap_string_string)をPythonメソッドに渡していますが、対応する引数のために渡されるPyObjectはキーだけを含むタプルです。値はどこにも渡されていないようです。 – peastman

+0

詳細な例を追加しました。やってみて。 –

+0

おっと、私のせいです。 (あるいは元々SWIGコードを作成した人の過ちでもあります)。すべての引数を前処理するコードがいくつかあったことが判明し、そのことがdictをタプルに変換していました。 – peastman