2015-04-06 155 views
0

我现在正在学习如何使用Boost::Python将C++类暴露给Python,并且我编写了下面的代码。使用Boost封装纯虚函数:: Python

编译代码是好的。但是,当我从导入的Python端的代码,它显示了以下错误:

回溯(最近通话最后一个): 文件 “test4.py”,1号线,在

import shape; 

导入错误:/ home/ruofan/Boost/Class/shape.so:undefined symbol:_ZTI7Polygon

我该如何解决这个问题?

#include <iostream> 
#include <boost/python.hpp> 

using namespace boost::python; 
using namespace std; 

class Polygon { 
    protected: 
    int width, height; 
    public: 
    Polygon (int a, int b) : width(a), height(b) {} 
    virtual int area (void) =0; 
    void printarea() 
     { cout << this->area() << '\n'; } 
    virtual ~Polygon(); 
}; 

class Rectangle: public Polygon { 
    public: 
    Rectangle(int a,int b) : Polygon(a,b) {} 
    int area() 
     { return width*height; } 
    virtual ~Rectangle(); 
}; 

class Triangle: public Polygon { 
    public: 
    Triangle(int a,int b) : Polygon(a,b) {} 
    int area() 
     { return width*height/2; } 
    virtual ~Triangle(); 
}; 

struct BaseWrap : Polygon, wrapper<Polygon> { 
    BaseWrap() : Polygon(0,0){} 
    int area(){ 
     return this->get_override("area")(); 
    } 
}; 


BOOST_PYTHON_MODULE(shape){ 
    class_<BaseWrap, boost::noncopyable>("Polygon") 
    .def("area", pure_virtual(&Polygon::area)); 
} 

回答

1

问题是,非纯虚拟函数正在被声明,但从来没有定义。这导致在库不必所属类别一类的未定义的引用:

$ c++filt c++filt _ZTI7Polygon 
typeinfo for Polygon 

在这种特殊情况下,析构函数从未定义:

class Polygon { 
    ... 
    public: 
    ... 
    virtual ~Polygon(); // Declared, but never defined. 
}; 

要解决此问题,定义Polygyon析:

class Polygon { 
    ... 
    public: 
    ... 
    virtual ~Polygon() = default; 
}; 

RectangleTriangle类型存在相同的问题。尽管可以省略声明其析构函数并允许编译器隐式生成它们。


用于包装纯虚函数的Boost.Python代码看起来很好。这是在原有基础上的代码一个完整的例子,demonstrates其用法:

#include <boost/python.hpp> 

// Mockup abstract type. 
class polygon 
{ 
protected: 
int width, height; 
public: 
    polygon(int a, int b): width(a), height(b) {} 
    virtual int area() = 0; 
    virtual ~polygon() = default; 
}; 

// Wrapper to allow calling Python overrides. 
struct polygon_wrap 
    : polygon, boost::python::wrapper<polygon> 
{ 
    polygon_wrap(): polygon(0, 0) {} 
    int area() { return this->get_override("area")(); } 
}; 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 

    // Expose models. 
    python::class_<polygon_wrap, boost::noncopyable>(
     "Polygon", python::init<>()) 
    .def("area", python::pure_virtual(&polygon::area)) 
    ; 
} 

互动用法:

>>> import example 
>>> class BadPolygon(example.Polygon): 
... pass 
... 
>>> class Square(example.Polygon): 
...  def __init__(self, length): 
...   example.Polygon.__init__(self) 
...   self.length = length 
...  def area(self): 
...   return self.length**2 
... 
>>> try: 
...  polygon = BadPolygon() 
...  assert(isinstance(polygon, example.Polygon)) 
...  got_runtime_error = False 
...  polygon.area() 
... except RuntimeError: 
...  got_runtime_error = True 
... finally: 
...  assert(got_runtime_error) 
... 
>>> polygon = Square(6) 
>>> assert(isinstance(polygon, example.Polygon)) 
>>> assert(36 == polygon.area()) 
+0

太谢谢你了!是的,你是对的,这真的很有帮助! – 2015-04-09 19:19:42