2013-05-20 39 views
6

我有一個C++類,我正在使用boost :: python構建成一個python模塊。我有幾個函數需要使用關鍵字參數。我已經設置了包裝函數傳遞給raw_arguments,並且工作正常,但我想建立一些錯誤檢查函數參數。有沒有一個標準的方法來做到這一點?在boost中從kwargs中提取參數:: python

我的函數原型,在C++中,看起來有點像這樣:

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

第三個參數是可選的,具有默認值爲0(我在的boost :: python的使用宏實現了這個直到現在)。在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 

有什麼在助推::蟒蛇或raw_function包裝,可以促進這一點,或者我需要編寫代碼來檢查這一切我?如果我需要,我怎樣才能提出例外情況?有沒有這樣做的標準方式?

回答

13

boost/python/args.hpp文件提供了一系列用於指定參數關鍵字的類。特別是,Boost.Python提供了一個arg類型,它表示一個潛在的關鍵字參數。它重載逗號運算符以允許更自然地定義參數列表。

MyClass暴露myFunctionmy_function,其中abc的關鍵詞參數,並c0默認值可以按如下方式寫入:

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)) 
    ; 
} 

下面是一個完整例如:

#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