2014-01-19 59 views
2

在我正在开发的游戏中,我有两个C++类(ICollidable和Sprite),它们的属性Position和Size都实际上继承了另一个名为Object的C++类。我有这三个类暴露在python与boost python。在蟒蛇Player类的构造函数看起来像这样的例子:虚拟继承C++和boost python

class Player(Game.ICollidable, Game.Sprite, Game.IKeyboardListener, Game.IEntity): 
    def __init__(self): 
     Game.IKeyboardListener.__init__(self) 
     Game.IEntity.__init__(self)  
     Game.ICollidable.__init__(self) 
     Game.Sprite.__init__(self) 

的问题是,当雪碧初始化到来之前ICollidable的初始化雪碧位置不正常,我不能重新定位精灵屏幕上。我认为最近发生的事情是,有些独立的Sprite和ICollidable位置实例,这是我在创建ICollidable类之前会发生的事情。

我尝试了各种各样的事情来尝试解决这个问题,并搜索互联网寻找解决方案,像这样的问题,但我已经空手而来了。任何意见,解决方案或提示将不胜感激。

编辑:

这些都是python绑定到我的C++类:

class_<Object>("GameObject") 
    .def_readwrite("Pos", &Object::pos) 
    .def_readwrite("Size",&Object::size) 
; 
class_<Sprite, bases<Object>>("Sprite", init<>()) 
    // Sprite(TexID, Pos) 
    .def(init<GLuint, glm::vec2>()) 
    // ---------------------------- 
    .def_readwrite("TexId", &Sprite::texid) 
; 
class_<ICollidableWrap, bases<Object>,boost::noncopyable>("ICollidable", init<>()) 
    //.def("Pos", &ICollidable::Object::pos) 
    .def("Test", pure_virtual(&ICollidable::Test)) 
    .def("OnCollision",pure_virtual(&ICollidable::OnCollision)) 
; 
+1

如果有用我将包括包装代码,暴露我的类到python – Steve

+0

我的第一个猜测是你通过值而不是通过引用传递参数,但它只是一个猜测,你应该提供更多的信息.​​.. –

+0

我已经在提高python绑定中添加,希望它可以提供有用的信息需要解决这个问题。 – Steve

回答

1

虽然两种语言提供一个解决the diamond problem,他们用不同的方法。 C++通过虚拟继承消除了不明确性,导致共享单个子对象。另一方面,Python通过单调超类线性化查找消除了模糊性。由于Python继承不会导致C++类型共享单个子对象,因此当Python类从两个共享公共虚拟基础的公开C++类继承时,Boost.Python需要模拟C++虚拟继承。不幸的是,尽我所知,Boost.Python不支持这种情况,因为提供给boost::python::bases<...>的类型未检查虚拟继承。

虽然不是可扩展的和可能的指示器,它可能是值得研究的基于组合物的解决方案中,一个简单的继承的解决方案是,以露出从ICollidableWrapSprite继承CollidableSprite C++类,然后从CollidableSprite具有Python类继承。


这是一个基本的例子,其中从BAC继承自V虚拟继承:

#include <boost/python.hpp> 

/// @brief Mock up forming the following multiple inheritance 
///  structure: 
/// 
///   .-->[ V ]<--. 
///   |   | 
///   [ A ]  [ B ] 
///   |   | 
///   '---[ C ] --' 
struct V 
{ 
    V() : x(0) {} 
    virtual ~V() {} 
    unsigned int x; 
}; 

struct A : virtual public V {}; 
struct B : virtual public V {}; 
struct C : public A, public B {}; 

/// @brief Functions that force an object's hierarchy chain to be 
///  split, disambiguating access to V.x. 
void print_a(A& a) { std::cout << a.x << std::endl; } 
void print_b(B& b) { std::cout << b.x << std::endl; } 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    // Expose hierarchy. 
    python::class_<V>("V", python::no_init) 
    .def_readwrite("x", &V::x) 
    ; 
    python::class_<A, python::bases<V> >("A"); 
    python::class_<B, python::bases<V> >("B"); 
    python::class_<C, python::bases<A, B> >("C"); 

    // Expose helper functions. 
    python::def("print_a", &print_a); 
    python::def("print_b", &print_b); 
} 

互动用法:

>>> import example 
>>> class PyC(example.A, example.B): 
...  def __init__(self): 
...   example.A.__init__(self) 
...   example.B.__init__(self) 
... 
>>> c = PyC() 
>>> example.print_a(c) 
0 
>>> example.print_b(c) 
0 
>>> c.x = 42 
>>> example.print_a(c) 
0 
>>> example.print_b(c) 
42 
>>> class PyC(example.C): 
...  pass 
... 
>>> c = PyC() 
>>> example.print_a(c) 
0 
>>> example.print_b(c) 
0 
>>> c.x = 42 
>>> example.print_a(c) 
42 
>>> example.print_b(c) 
42 
+0

谢谢你的回答,这是我将要解决的问题。 – Steve