В этом конкретном случае сообщение об ошибке вводит в заблуждение. Функция получает аргумент с правом типа; однако аргумент имеет несоответствующее значение . Инициализатор Bar
не инициализирует часть своей иерархии Python Base
. Экземпляр Python не содержит boost::shared_ptr<Base>
экземпляр, в результате чего Boost.Python не в состоянии направить на C++ функции:
class Bar(Base):
def __init__(self):
pass # Base is not initialized.
fun(Base()) # No boost::shared_ptr<Base> instance.
Чтобы решить эту проблему, явно вызывать Base.__init__()
в Bar.__init__()
:
class Bar(Base):
def __init__(self):
Base.__init__(self) # Instantiates boost::shared_ptr<Base>.
fun(Bar()) # Boost.Python will extract boost::shared_ptr<Base> from Bar().
Подробнее о Python, если производный класс определяет метод __init__()
, тогда он должен явно вызвать метод родительского класса '__init__()
. Документация Python states:
Если базовый класс имеет __init__()
метод, __init__()
метод производного класса, если таковые имеются, необходимо вызвать его для обеспечения надлежащей инициализации базового класса части экземпляра; например: BaseClass.__init__(self, [args...])
.
В Boost.Python оболочки класса C++ имеют instance_holder
. Эти объекты держать экземпляры C++ в их Python объект оболочки, и конкретизация объекта в C++ происходит в __init__
функции объекта в Python:
Когда __init__
функции для класса обернутого C++ вызывается, новый instance_holder
экземпляр создаются и установлен в объекте Python [...]
Поэтому, если метод объекта Python в __init__()
не вызывается, объект внутреннего C++ не будет экземпляр. Когда открытая функция C++ вызывается из Python, Boost.Python будет исследовать аргументы вызова, пытаясь идентифицировать соответствующую функцию C++ в рамках набора открытых функций.Если совпадение не найдено, оно вызывает исключение Boost.Python.ArgumentError
, в котором перечислены типы аргументов и набор функций C++, для которых он не совпал.
Вот полный пример demonstrating, имеющий два различных типа Python наследовать от типа открытой C++, где одна иерархия инициализирован правильно, а другой нет:
#include <boost/python.hpp>
struct base {};
void foo(boost::shared_ptr<base>) {}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<base, boost::shared_ptr<base>, boost::noncopyable>(
"Base", python::init<>())
;
python::def("foo", &foo);
}
Интерактивное использование:
>>> import example
>>> class GoodDerived(example.Base):
... def __init__(self):
... example.Base.__init__(self)
...
>>> class BadDerived(example.Base):
... def __init__(self):
... pass
...
>>> assert(isinstance(GoodDerived(), example.Base))
>>> assert(isinstance(BadDerived(), example.Base))
>>> try:
... example.foo(GoodDerived())
... got_exception = False
... except:
... got_exception = True
... finally:
... assert(not got_exception)
...
>>> try:
... example.foo(BadDerived())
... got_exception = False
... except:
... got_exception = True
... finally:
... assert(got_exception)
Обратите внимание, что хотя иерархия типов правильная и проверяемая с помощью isinstance(()
, типы не указывают, имеет ли экземпляр экземпляр надлежащее значение.
Я попробую это, когда вернусь к своему компьютеру! –
Ты спасатель, спасибо. –