Boost.Python: __init__ принимает аргумент None - PullRequest
1 голос
/ 02 декабря 2009

У меня есть тип значения C ++, обернутый Boost.Python, который имеет концепцию значения NULL. Соответствующие части кода оболочки выглядят следующим образом:

class_<TCurrency> currency( "TCurrency" )
    .def( init<long>() )
    .def( init<const std::string&>() )
    <...>;

В настоящее время попытка создать экземпляр NULL в Python путем передачи None методу __init__() приводит к тому, что C ++, принимающий ссылку на константную строку, вызывается с недопустимой ссылкой. (&arg == NULL)

Можно ли отследить случай, когда None передается конструктору, и обработать его изящно или, по крайней мере, вызвать значимое исключение до того, как моя программа потерпит крах?

Использование Boost 1.36 и Python 2.6.2.

1 Ответ

2 голосов
/ 02 декабря 2009

Добавление перегрузки init<void*> пройдет NULL, если None используется, но я не уверен, как это может повлиять на другие ctors в угловых случаях. Я также не получаю того же константа и преобразования None to string, о котором вы упомянули, если я пропущу init<void*>. Использование Boost.Python 1.37 и Python 2.6.2.

Пример:

#include <iostream>
#include <string>

#include <boost/python.hpp>


struct A {
#define BODY { std::cout << __PRETTY_FUNCTION__ << '\n'; }
    A() BODY
    A(long) BODY
    A(std::string const&) BODY
    A(void* p) BODY
#undef BODY
};

BOOST_PYTHON_MODULE(ex) {
using namespace boost::python;
class_<A>("A")
    .def(init<long>())
    .def(init<std::string const&>())
    .def(init<void*>())
;
}
>>> import ex
>>> ex.A()
A::A()
<ex.A object at 0x839bf7c>
>>> ex.A(42)
A::A(long int)
<ex.A object at 0x839bfcc>
>>> ex.A("abc")
A::A(const std::string&)
<ex.A object at 0x839bf7c>
>>> ex.A(None)
A::A(void*)
<ex.A object at 0x839bfcc>

Если init<void*> опущено:

>>> ex.A(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
    A.__init__(A, NoneType)
did not match C++ signature:
    __init__(_object*, std::string)
    __init__(_object*, long)
    __init__(_object*)
...