2013-05-20 5 views
6

私はboost :: pythonを使ってPythonモジュールに組み込んでいるC++クラスを持っています。私はキーワード引数を取るいくつかの関数を持っています。私はraw_argumentsに渡すラッパー関数を設定していますが、うまくいきますが、関数の引数を調べる際に何らかのエラーチェックをしたいのです。これを行う標準的な方法はありますか?boost :: pythonのkwargsから引数を抽出する

double MyClass::myFunction(int a, int b, int c); 

3番目の引数はデフォルト値の0で、省略可能です(私はマクロを使い切ってブースト:: pythonでこれを実装しました:

私の関数のプロトタイプは、C++で、このようなビットに見えます今まで)。 Pythonでは、私は、次の動作を実現することができるようにしたい:

MyClass.my_function(1) # Raises exception 
MyClass.my_function(2, 3) # So that a = 2, b = 3 and c defaults to 0 
MyClass.my_function(2, 3, 1) # As above, but now c = 1 
MyClass.my_function(2, 3, 1, 3) # Raises exception 
MyClass.my_function(3, 1, c = 2) # So a = 3, b = 1 and c = 2 
MyClass.my_function(a = 2, b = 2, c = 3) # Speaks for itself 
MyClass.my_function(b = 2, c = 1) # Raises exception 

はブースト::のpythonまたはこれを容易にすることができるraw_functionラッパーで何かがある、または私はこのすべてをチェックするコードを記述する必要があります私自身?必要があれば、どうすれば例外を引き上げることができますか?これを行う標準的な方法はありますか?

答えて

13

boost/python/args.hppファイルには、引数キーワードを指定するためのクラスファミリが用意されています。特に、Boost.Pythonは潜在的なキーワード引数を表すargタイプを提供します。コンマ演算子をオーバーロードして、引数リストのより自然な定義を可能にします。ここで

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    python::class_<MyClass>("MyClass") 
    .def("my_function", &MyClass::myFunction, 
     (python::arg("a"), "b", python::arg("c")=0)) 
    ; 
} 

は完了です:ab、およびcはキーワード引数であり、cは次のように0のデフォルト値が書き込まれる可能性がありmy_function、などMyClassmyFunctionを公開

例:

#include <boost/python.hpp> 

class MyClass 
{ 
public: 
    double myFunction(int a, int b, int c) 
    { 
    return a + b + c; 
    } 
}; 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    python::class_<MyClass>("MyClass") 
    .def("my_function", &MyClass::myFunction, 
     (python::arg("a"), "b", python::arg("c")=0)) 
    ; 
} 

対話型使用法:完全に働いた、そしてそれは私が知らず知らずのうちにその関数の引数をオーバーロードするために別の関数に同様の設定を使用したいことを少し恥ずかしいです

>>> import example 
>>> my_class = example.MyClass() 
>>> my_class.my_function(1) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
Boost.Python.ArgumentError: Python argument types in 
    MyClass.my_function(MyClass, int) 
did not match C++ signature: 
    my_function(MyClass {lvalue}, int a, int b, int c=0) 
>>> assert(5 == my_class.my_function(2, 3)) 
>>> assert(6 == my_class.my_function(2, 3, 1)) 
>>> my_class.my_function(2, 3, 1, 3) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
Boost.Python.ArgumentError: Python argument types in 
    MyClass.my_function(MyClass, int, int, int, int) 
did not match C++ signature: 
    my_function(MyClass {lvalue}, int a, int b, int c=0) 
>>> assert(6 == my_class.my_function(3, 1, c=2)) 
>>> assert(7 == my_class.my_function(a=2, b=2, c=3)) 
>>> my_class.my_function(b=2, c=1) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
Boost.Python.ArgumentError: Python argument types in 
    MyClass.my_function(MyClass) 
did not match C++ signature: 
    my_function(MyClass {lvalue}, int a, int b, int c=0) 
+0

。これはコンストラクタでも使えますか? – orentago

+0

私自身の質問に答えるには:そうです。 Py :: init ((py :: arg( "a")、py :: arg( "b")...))引数タイプをリストします。 – orentago

+0

(誰でもこの作業に問題がある場合は、argsを囲む追加の括弧に注意してください) – ricab

関連する問題