<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 10pt;
font-family:Tahoma
}
--></style></head>
<body class='hmmessage'><div dir='ltr'>
I've been looking around and I can find tons of information about how to wrap shallow inheritance hierarchys with virtual/pure virtual functions, but none of them show how to do multi level inheritance. I'm unsure if I'm supposed to inherit from the wrapper or the base class for the virtual functions. Essentially, I'm asking what the best way to wrap this, the various methods I've tried usually result in error messages about the wrapper not being available<div><br></div><div>For Instance I have this hierarchy:</div><div><br></div><div><div>class DrawInterface</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>public:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>DrawInterface(int drawPriority = 0, bool drawing = true) : DrawPriority(drawPriority), Drawing(drawing)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>bool IsDrawing() const</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>return Drawing;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>void SetDrawing(const bool value)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>Drawing = value;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>virtual void Draw(sf::RenderWindow &amp;window) = 0;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>virtual void Draw(sf::RenderWindow &amp;window, sf::Shader &amp;shader) = 0;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>int GetDrawPriority() const</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>return DrawPriority;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>private:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>bool Drawing;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>int DrawPriority;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>};</div></div><div><br></div><div><div>class AnimatedDraw : public DrawInterface</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>public:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>AnimatedDraw(bool paused = false, int drawPriority = 0) : DrawInterface(drawPriority), Paused(paused)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>virtual void Update(const sf::Uint32 time, const float TimeScale = 1.0) = 0;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>virtual void Update(const float time, const float TimeScale = 1.0) = 0;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>virtual void SetPause(const bool value)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>Paused = value;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>virtual bool GetPause() const</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>return Paused;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>protected:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>bool Paused;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>private:</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>};</div></div><div><br></div><div><div>class InputInterface</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>public:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>InputInterface(bool acceptingInputs = true) : AcceptingInputs(acceptingInputs)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>bool IsAcceptingInputs() const</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>return AcceptingInputs;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>void SetAcceptingInputs(const bool value)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>AcceptingInputs = value;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>virtual bool HandleKeyPressed(const sf::Uint32 time, const ::Input::InputModule* inputModule, ::Input::PlayerInput pInput, ::Input::InputAction&amp; action) { return false;}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>virtual bool HandleKeyReleased(const sf::Uint32 time, const ::Input::InputModule* inputModule, ::Input::PlayerInput pInput, ::Input::InputAction&amp; action) { return false;}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>private:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>bool AcceptingInputs;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>};</div></div><div><br></div><div><div>class Screen : public ::Input::InputInterface, public AnimatedDraw</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>public:</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>Screen(const std::string&amp; name, ::Engine* engine, int id);</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>int GetID() const;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>const std::string&amp; GetScreenName() const;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>void SetScreenName(const std::string&amp; name);</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>bool AddOwner(const std::string&amp; name, ScreenStack* stack);</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>bool RemoveOwner(const std::string&amp; name);</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>bool HasOwner(const std::string&amp; name) const;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>const boost::unordered_map&lt;std::string, ScreenStack*&gt;&amp; GetOwners() const;</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>bool operator==(const Screen&amp; screen) const;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>bool operator!=(const Screen&amp; screen) const;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>private:</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>Engine* engine;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>int ScreenID;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>std::string ScreenName;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>sf::Uint32 LastUpdate;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>boost::unordered_map&lt;std::string, ScreenStack*&gt; OwningStacks;</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>friend class ScreenManager;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>};</div></div><div><br></div><div>I want to be able to create various types of screens in Python so obviously I need to expose/wrap all the base classes, but this is where I get a little unclear about if I should be inheriting from the wrappers or the base classes, and how I should be representing these clases in python. My initial attempt at wrapping looked something like this:</div><div><br></div><div><div>class DrawInterfaceWrap : public DrawInterface</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>public:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>DrawInterfaceWrap(PyObject* self, int priority = 0, bool drawing = true) : self(self), DrawInterface(priority, drawing)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>DrawInterfaceWrap(PyObject* self, const DrawInterface&amp; src) : self(self), DrawInterface(src)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>void Draw(sf::RenderWindow &amp;window) override</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>call_method&lt;void&gt;(self, "Draw", boost::ref(window));</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>void Draw(sf::RenderWindow &amp;window, sf::Shader&amp; shader) override</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>call_method&lt;void&gt;(self, "Draw", boost::ref(window), boost::ref(shader));</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>private:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>PyObject* self;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>};</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>class AnimatedDrawWrap : public AnimatedDraw</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>public:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>AnimatedDrawWrap(PyObject* self, int priority = 0, bool paused = true) : self(self), AnimatedDraw(paused, priority)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>//??? not sure how to do ta proper copy construction on self</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>AnimatedDrawWrap(PyObject* self, const AnimatedDraw&amp; src) : self(self), AnimatedDraw(src)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>void Update(const sf::Uint32 time, const float TimeScale = 1.0) override</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>call_method&lt;void&gt;(self, "Update", time, TimeScale);</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>void Update(float time, const float TimeScale = 1.0) override</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>call_method&lt;void&gt;(self, "Update", time, TimeScale);</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>private:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>PyObject* self;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>};</div></div><div><br></div><div><div>class_&lt;DrawInterfaceWrap&gt;("DrawInterface", init&lt;boost::python::optional&lt;int, bool&gt; &gt;())</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def(init&lt;const DrawInterface&amp;&gt;())</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("Draw", pure_virtual((void (DrawInterface::*)(sf::RenderWindow&amp;))&amp;DrawInterface::Draw))</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("Draw", pure_virtual((void (DrawInterface::*)(sf::RenderWindow&amp;, sf::Shader&amp;))&amp;DrawInterface::Draw))</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("IsDrawing", &amp;DrawInterface::IsDrawing)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("SetDrawing", &amp;DrawInterface::SetDrawing)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("GetDrawPriority", &amp;DrawInterface::GetDrawPriority)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>class_&lt;AnimatedDrawWrap, bases&lt;DrawInterfaceWrap&gt; &gt;("AnimatedDraw", init&lt;boost::python::optional&lt;int, bool&gt; &gt;())</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def(init&lt;const AnimatedDraw&amp;&gt;())</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def(init&lt;const AnimatedDrawWrap&amp;&gt;())</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("Update", pure_virtual((void (AnimatedDraw::*)(const sf::Uint32, const float))&amp;AnimatedDraw::Update))</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("Update", pure_virtual((void (AnimatedDraw::*)(const float, const float))&amp;AnimatedDraw::Update))</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("GetPause", &amp;AnimatedDraw::GetPause)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("SetPause", &amp;AnimatedDraw::SetPause)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>;</div></div><div><br></div><div><div>class InputInterfaceWrap : public ::Input::InputInterface</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>public:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>InputInterfaceWrap(PyObject* self, bool acceptingInputs = true) : self(self), ::Input::InputInterface(acceptingInputs)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>virtual bool HandleKeyPressed(const sf::Uint32 time, const ::Input::InputModule* inputModule, ::Input::PlayerInput pInput, ::Input::InputAction&amp; action) override</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>return call_method&lt;bool&gt;(self, "HandleKeyPressed", time, ptr(inputModule), pInput, boost::ref(action));</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>virtual bool HandleKeyReleased(const sf::Uint32 time, const ::Input::InputModule* inputModule, ::Input::PlayerInput pInput, ::Input::InputAction&amp; action) override</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>{</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>return call_method&lt;bool&gt;(self, "HandleKeyReleased", time, ptr(inputModule), pInput, boost::ref(action));</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>private:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>PyObject* self;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>};</div></div><div><br></div><div><div>class_&lt;InputInterfaceWrap, boost::noncopyable&gt;("InputInteface", init&lt;boost::python::optional&lt;bool&gt; &gt;())</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("HandleKeyPressed", pure_virtual(&amp;::Input::InputInterface::HandleKeyPressed))</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("HandleKeyReleased", pure_virtual(&amp;::Input::InputInterface::HandleKeyReleased))</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("IsAcceptingInputs", &amp;::Input::InputInterface::IsAcceptingInputs)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("SetAcceptingInputs", &amp;::Input::InputInterface::SetAcceptingInputs)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>;</div></div><div><br></div><div><div>class_&lt;Screen, bases&lt;Graphics::AnimatedDraw, ::Input::InputInterface&gt; &gt;("Screen", init&lt;const std::string&amp;, ::Engine*, int&gt;())</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("GetID", &amp;Screen::GetID)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("GetScreenName", &amp;Screen::GetScreenName, return_value_policy&lt;reference_existing_object&gt;())</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("HasOwner", &amp;Screen::HasOwner)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("RemoveOwner", &amp;Screen::RemoveOwner)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>.def("SetScreenName", &amp;Screen::SetScreenName)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>;</div></div><div><br></div><div>I cant export this wrapping because boost python won't let me have initializers for abstract classes. I attempted to fix this by changing all the pure virtual functions to virtual functions, and adding a&nbsp;Default&nbsp;method for each virtual function in the wrapper. I was able to compile like this, but python hits a runtime error saying a wrapper is unavailable for base class AnimatedDraw, so obviously my exports are sstill incorrect. I'm looking for advice on how to export this hierarchy. Can I keep these&nbsp;functions&nbsp;pure virtual and have initializers or will I need to add a default implementation? Further to that, should I be inheriting from the wrappers and not the base classes? I&nbsp;really&nbsp;just want this to work where I can inherit from Screen and&nbsp;implement&nbsp;Update, Draw and HandleKeys for each screen.</div><div><br></div><div>I had an additional question. How do you correctly implement a copy constructors on the wrapper classes?</div><div>for instance this:</div><div><div>AnimatedDrawWrap(PyObject* self, const AnimatedDraw&amp; src) : self(self), AnimatedDraw(src)</div><div><span class="Apple-tab-span" style="white-space: pre; ">                </span>{</div><div><br></div><div><span class="Apple-tab-span" style="white-space: pre; ">                </span>}</div></div><div><br></div><div>I assume is incorrect since I'm not making a proper copy of the self pointer. What's the correct way to do this?</div><div><br></div><div>My last question is more a sylistic one. I've seen multiple ways to implement the virtual function override. I've chosen the call_method form:</div><div><br></div><div><div>void Update(const sf::Uint32 time, const float TimeScale = 1.0) override</div><div><span class="Apple-tab-span" style="white-space: pre; ">                </span>{</div><div><span class="Apple-tab-span" style="white-space: pre; ">                        </span>call_method&lt;void&gt;(self, "Update", time, TimeScale);</div><div><span class="Apple-tab-span" style="white-space: pre; ">                </span>}</div></div><div><br></div><div>just because&nbsp;that's&nbsp;what I'm used to. Is there a "better" or more correct way to do this? or is it a purely stylistic choice?</div><div><br></div><div>Sorry for the cluster of code, I hope my questions are clear. I can clean out some parts of the code that I don't think are relevant, but since the classes are fairly small to begin with, I figured it'd be okay.</div><div><br></div><div>Thanks on advance for any help :)</div>                                               </div></body>
</html>