2013-05-20 3 views
6

У меня есть класс C++, который я создаю в модуле python, используя boost :: python. У меня есть несколько функций, которые я хочу использовать для аргументов ключевых слов. Я установил функции-обертки, чтобы перейти к raw_arguments, и это работает нормально, но я хочу построить некоторую проверку ошибок для аргументов функции. Есть ли стандартный способ сделать это?Извлечение аргументов из kwargs в boost :: python

Мой прототип функции в C++, немного похож на это:

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

Третий аргумент является необязательным, со значением по умолчанию 0 (я реализовал это в буст :: питона с помощью макросов вверх до настоящего времени). В 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, который представляет потенциальный аргумент ключевого слова. Он перегружает оператор запятой, чтобы обеспечить более естественное определение списка аргументов.

Разоблачение myFunction на MyClass в my_function, где a, b и c являются ключевые аргументы, и c имеет значение по умолчанию 0 можно записать следующим образом:

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

Смежные вопросы