为什么 Boost Python 试图实例化一个抽象类型?
Why is Boost Python trying to instantiate an abstract type?
我有以下 C++ class:
#include <cmath>
#include <stdexcept>
#include <string>
struct AbstractShape
{
virtual ~AbstractShape() { }
virtual double area() const noexcept = 0;
};
class Square : public AbstractShape
{
const double side_;
public:
double area() const noexcept override {
return side_ * side_;
}
Square(double side) : side_(side) { }
};
和以下 Boost python 绑定:
#include "Shape.h"
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(Shape)
{
using namespace boost::python;
struct AbstractShapeWrap : AbstractShape, wrapper<AbstractShape>
{
double area() {
if(override area = this->get_override("area"))
return area();
return AbstractShape::area();
}
double default_area() {
return AbstractShape::area();
}
};
class_<AbstractShape>("AbstractShape", no_init)
.add_property("area", &AbstractShape::area, &AbstractShapeWrap::default_area)
;
class_<Square, bases<AbstractShape> >("Square", init<double>())
;
}
当我编译时:
clang++ -std=c++14 Shape.py.cpp -c $(python3-config --includes)
我得到:
In file included from Shape.py.cpp:3:
In file included from /usr/local/include/boost/python.hpp:18:
In file included from /usr/local/include/boost/python/class.hpp:23:
In file included from /usr/local/include/boost/python/object/class_metadata.hpp:14:
/usr/local/include/boost/python/object/value_holder.hpp:62:11: error: field type 'AbstractShape' is an abstract class
Value m_held;
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/type_traits:1568:40: note: in instantiation of template class
'boost::python::objects::value_holder<AbstractShape>' requested here
: public integral_constant<size_t, __alignof__(_Tp)> {};
^
/usr/local/include/boost/python/object/instance.hpp:29:32: note: in instantiation of template class 'std::__1::alignment_of<boost::python::objects::value_holder<AbstractShape> >'
requested here
boost::python::detail::alignment_of<Data>::value
^
/usr/local/include/boost/python/object/instance.hpp:45:30: note: in instantiation of template class
'boost::python::objects::instance<boost::python::objects::value_holder<AbstractShape> >' requested here
std::size_t, value = sizeof(instance_data)
^
/usr/local/include/boost/python/object/make_instance.hpp:36:28: note: in instantiation of template class
'boost::python::objects::additional_instance_size<boost::python::objects::value_holder<AbstractShape> >' requested here
type, objects::additional_instance_size<Holder>::value);
^
/usr/local/include/boost/python/object/class_wrapper.hpp:29:30: note: in instantiation of function template specialization 'boost::python::objects::make_instance_impl<AbstractShape,
boost::python::objects::value_holder<AbstractShape>, boost::python::objects::make_instance<AbstractShape, boost::python::objects::value_holder<AbstractShape> >
>::execute<const boost::reference_wrapper<const AbstractShape> >' requested here
return MakeInstance::execute(boost::ref(x));
^
/usr/local/include/boost/python/converter/as_to_python_function.hpp:27:72: note: (skipping 4 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
convert_function_must_take_value_or_const_reference(&ToPython::convert, 1L);
^
/usr/local/include/boost/python/object/class_metadata.hpp:218:25: note: in instantiation of function template specialization 'boost::python::objects::class_metadata<AbstractShape,
boost::python::detail::not_specified, boost::python::detail::not_specified, boost::python::detail::not_specified>::register_aux2<AbstractShape, boost::integral_constant<bool,
false> >' requested here
class_metadata::register_aux2((T*)0, use_callback());
^
/usr/local/include/boost/python/object/class_metadata.hpp:204:25: note: in instantiation of member function 'boost::python::objects::class_metadata<AbstractShape,
boost::python::detail::not_specified, boost::python::detail::not_specified, boost::python::detail::not_specified>::register_aux' requested here
class_metadata::register_aux((T*)0);
^
/usr/local/include/boost/python/class.hpp:460:19: note: in instantiation of member function 'boost::python::objects::class_metadata<AbstractShape,
boost::python::detail::not_specified, boost::python::detail::not_specified, boost::python::detail::not_specified>::register_' requested here
metadata::register_(); // set up runtime metadata/conversions
^
/usr/local/include/boost/python/class.hpp:591:11: note: in instantiation of member function 'boost::python::class_<AbstractShape, boost::python::detail::not_specified,
boost::python::detail::not_specified, boost::python::detail::not_specified>::initialize' requested here
this->initialize(no_init);
^
Shape.py.cpp:22:7: note: in instantiation of member function 'boost::python::class_<AbstractShape, boost::python::detail::not_specified, boost::python::detail::not_specified,
boost::python::detail::not_specified>::class_' requested here
class_<AbstractShape>("AbstractShape", no_init)
^
./Shape.h:8:22: note: unimplemented pure virtual method 'area' in 'AbstractShape'
virtual double area() const noexcept = 0;
^
1 error generated.
为什么 boost::python 试图实例化抽象 class?
我的绑定或调用需要更改什么?
缺少 boost::noncopyable
可能是根本原因,即
class_<AbstractShape, boost::noncopyable>("AbstractShape", no_init)
另外像 AbstractShape::area()
这样的东西可能不应该工作,因为它是一个纯虚拟方法。
Shape.h
struct AbstractShape
{
virtual ~AbstractShape() { }
virtual double area() const noexcept = 0;
};
class Square : public AbstractShape
{
const double side_;
public:
double area() const noexcept override {
return side_ * side_;
}
Square(double side) : side_(side) { }
};
Shape.py.cpp
#include <boost/python.hpp>
#include "Shape.h"
BOOST_PYTHON_MODULE(Shape)
{
using namespace boost::python;
struct AbstractShapeWrap : AbstractShape, wrapper<AbstractShape> {
double area() {
return this->get_override("area")();
}
double default_area() {
return this->get_override("area")();
}
};
class_<AbstractShape, boost::noncopyable>("AbstractShape", no_init)
.add_property("area", &AbstractShape::area,
&AbstractShapeWrap::default_area);
class_<Square, bases<AbstractShape> >("Square", init<double>());
}
我有以下 C++ class:
#include <cmath>
#include <stdexcept>
#include <string>
struct AbstractShape
{
virtual ~AbstractShape() { }
virtual double area() const noexcept = 0;
};
class Square : public AbstractShape
{
const double side_;
public:
double area() const noexcept override {
return side_ * side_;
}
Square(double side) : side_(side) { }
};
和以下 Boost python 绑定: #include "Shape.h"
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(Shape)
{
using namespace boost::python;
struct AbstractShapeWrap : AbstractShape, wrapper<AbstractShape>
{
double area() {
if(override area = this->get_override("area"))
return area();
return AbstractShape::area();
}
double default_area() {
return AbstractShape::area();
}
};
class_<AbstractShape>("AbstractShape", no_init)
.add_property("area", &AbstractShape::area, &AbstractShapeWrap::default_area)
;
class_<Square, bases<AbstractShape> >("Square", init<double>())
;
}
当我编译时:
clang++ -std=c++14 Shape.py.cpp -c $(python3-config --includes)
我得到:
In file included from Shape.py.cpp:3:
In file included from /usr/local/include/boost/python.hpp:18:
In file included from /usr/local/include/boost/python/class.hpp:23:
In file included from /usr/local/include/boost/python/object/class_metadata.hpp:14:
/usr/local/include/boost/python/object/value_holder.hpp:62:11: error: field type 'AbstractShape' is an abstract class
Value m_held;
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/type_traits:1568:40: note: in instantiation of template class
'boost::python::objects::value_holder<AbstractShape>' requested here
: public integral_constant<size_t, __alignof__(_Tp)> {};
^
/usr/local/include/boost/python/object/instance.hpp:29:32: note: in instantiation of template class 'std::__1::alignment_of<boost::python::objects::value_holder<AbstractShape> >'
requested here
boost::python::detail::alignment_of<Data>::value
^
/usr/local/include/boost/python/object/instance.hpp:45:30: note: in instantiation of template class
'boost::python::objects::instance<boost::python::objects::value_holder<AbstractShape> >' requested here
std::size_t, value = sizeof(instance_data)
^
/usr/local/include/boost/python/object/make_instance.hpp:36:28: note: in instantiation of template class
'boost::python::objects::additional_instance_size<boost::python::objects::value_holder<AbstractShape> >' requested here
type, objects::additional_instance_size<Holder>::value);
^
/usr/local/include/boost/python/object/class_wrapper.hpp:29:30: note: in instantiation of function template specialization 'boost::python::objects::make_instance_impl<AbstractShape,
boost::python::objects::value_holder<AbstractShape>, boost::python::objects::make_instance<AbstractShape, boost::python::objects::value_holder<AbstractShape> >
>::execute<const boost::reference_wrapper<const AbstractShape> >' requested here
return MakeInstance::execute(boost::ref(x));
^
/usr/local/include/boost/python/converter/as_to_python_function.hpp:27:72: note: (skipping 4 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
convert_function_must_take_value_or_const_reference(&ToPython::convert, 1L);
^
/usr/local/include/boost/python/object/class_metadata.hpp:218:25: note: in instantiation of function template specialization 'boost::python::objects::class_metadata<AbstractShape,
boost::python::detail::not_specified, boost::python::detail::not_specified, boost::python::detail::not_specified>::register_aux2<AbstractShape, boost::integral_constant<bool,
false> >' requested here
class_metadata::register_aux2((T*)0, use_callback());
^
/usr/local/include/boost/python/object/class_metadata.hpp:204:25: note: in instantiation of member function 'boost::python::objects::class_metadata<AbstractShape,
boost::python::detail::not_specified, boost::python::detail::not_specified, boost::python::detail::not_specified>::register_aux' requested here
class_metadata::register_aux((T*)0);
^
/usr/local/include/boost/python/class.hpp:460:19: note: in instantiation of member function 'boost::python::objects::class_metadata<AbstractShape,
boost::python::detail::not_specified, boost::python::detail::not_specified, boost::python::detail::not_specified>::register_' requested here
metadata::register_(); // set up runtime metadata/conversions
^
/usr/local/include/boost/python/class.hpp:591:11: note: in instantiation of member function 'boost::python::class_<AbstractShape, boost::python::detail::not_specified,
boost::python::detail::not_specified, boost::python::detail::not_specified>::initialize' requested here
this->initialize(no_init);
^
Shape.py.cpp:22:7: note: in instantiation of member function 'boost::python::class_<AbstractShape, boost::python::detail::not_specified, boost::python::detail::not_specified,
boost::python::detail::not_specified>::class_' requested here
class_<AbstractShape>("AbstractShape", no_init)
^
./Shape.h:8:22: note: unimplemented pure virtual method 'area' in 'AbstractShape'
virtual double area() const noexcept = 0;
^
1 error generated.
为什么 boost::python 试图实例化抽象 class?
我的绑定或调用需要更改什么?
缺少 boost::noncopyable
可能是根本原因,即
class_<AbstractShape, boost::noncopyable>("AbstractShape", no_init)
另外像 AbstractShape::area()
这样的东西可能不应该工作,因为它是一个纯虚拟方法。
Shape.h
struct AbstractShape
{
virtual ~AbstractShape() { }
virtual double area() const noexcept = 0;
};
class Square : public AbstractShape
{
const double side_;
public:
double area() const noexcept override {
return side_ * side_;
}
Square(double side) : side_(side) { }
};
Shape.py.cpp
#include <boost/python.hpp>
#include "Shape.h"
BOOST_PYTHON_MODULE(Shape)
{
using namespace boost::python;
struct AbstractShapeWrap : AbstractShape, wrapper<AbstractShape> {
double area() {
return this->get_override("area")();
}
double default_area() {
return this->get_override("area")();
}
};
class_<AbstractShape, boost::noncopyable>("AbstractShape", no_init)
.add_property("area", &AbstractShape::area,
&AbstractShapeWrap::default_area);
class_<Square, bases<AbstractShape> >("Square", init<double>());
}