Я пытаюсь выставить свои классы C++ на Python с помощью Boost.Python. Вот simplyfied версия о том, что я пытаюсь сделать:ТипError: нет конвертера to_python (по значению) для типа C++
struct Base {
virtual ~Base() {};
virtual char const *Hello() {
printf("Base.Hello\n");
return "Hello. I'm Base.";
};
};
struct Derived : Base {
char const *Hello() {
printf("Derived.Hello\n");
return "Hello. I'm Derived.";
};
Base &test() {
printf("Derived.test\n");
// ...
// After some calculation, we get result reference `instance'
// `instance' can be an instance of Base or Derived.
// ...
return instance;
}
};
Я хочу использовать выше классы следующим образом в Python:
instance = Derived()
// If method test returns an instance of Base
instance.test().Hello() // Result: "Hello. I'm Base."
// If method test returns an instance of Derived
instance.test().Hello() // Result: "Hello. I'm Derived."
Я не знаю ни одного красивого решения этой проблемы , Я просто попытался это:
struct BaseWrapper : Base, wrapper<Base> {
char const *Hello() {
printf("BaseWrapper.Hello\n");
if (override Hello = this->get_override("Hello")) {
return Hello();
}
return Base::Hello();
}
char const *default_Hello() {
printf("BaseWrapper.default_Hello\n");
return this->Base::Hello();
}
};
struct DerivedWrapper : Derived, wrapper<Derived> {
char const *Hello() {
printf("DerivedWrapper.Hello\n");
if (override Hello = this->get_override("Hello")) {
return Hello();
}
return Derived::Hello();
}
char const *default_Hello() {
printf("DerivedWrapper.default_Hello\n");
return this->Derived::Hello();
}
Base &test() {
printf("DerivedWrapper.test\n");
if (override Hello = this->get_override("test")) {
return Hello();
}
return Derived::test();
}
Base &default_test() {
printf("DerivedWrapper.default_test\n");
return this->Derived::test();
}
};
И их, я использую следующий код:
BOOST_PYTHON_MODULE(Wrapper) {
class_<BaseWrapper, boost::noncopyable>("Base")
.def("Hello", &Base::Hello, &BaseWrapper::default_Hello);
class_<DerivedWrapper, boost::noncopyable, bases<Base> >("Derived")
.def("Hello", &Derived::Hello, &DerivedWrapper::default_Hello)
.def("test", &Derived::test, return_value_policy<copy_non_const_reference>());
}
Но когда я скомпилированный выше кода в .so файл, и используется в питона
derived = Wrapper.Derived()
derived.test()
Он исключает исключение:
TypeError: No to_python (by-value) converter found for C++ type: Base
Этот пост имеет ту же ошибку, что и у меня, но по-другому это мне не очень помогло. Boost.Python call by reference : TypeError: No to_python (by-value) converter found for C++ type:
Этот пост решает аналогичную проблему, но мне тоже не помогло. https://github.com/BVLC/caffe/issues/3494
У меня есть две проблемы:
- Если так, как я пытался это правильный путь, как решить эту проблему TypeError?
- Если я попробовал неправильный путь, тогда какой лучший способ решить проблему с помощью boost.python?
Спасибо за ваше решение, она решить мою проблему. Я также нашел руководство: [link] (http://www.boost.org/doc/libs/1_45_0/libs/python/doc/v2/return_internal_reference.html) –