Boost C++ Libraries: Ticket #138: problem with overridable virtual functions in Boost.Python https://svn.boost.org/trac10/ticket/138 <pre class="wiki">I'm having problems overriding functions in Python with Boost. The examples provided on the website seem to work. However, all the examples I have managed to find have involved callback classes with virtual function overrides having zero arguments. I am trying to override functions with multiple arguments with no success. I get consistent errors when trying to manipulate multi-argument virtual functions polymorphically from a C++ extension. Im currently using Visual Studio .Net and Python 2.2.2. The following code demostrates the problem: ------------------Begin Code --------------------------- C++ code: #include &lt;iostream&gt; #include &lt;string&gt; class Entity { public: Entity() {Class = "Entity"; } Entity(const Entity&amp; e) { this-&gt;Class = e.Class; } std::string virtual GetClass(std::string PreFix) { return Class + PreFix; } public: std::string Class; }; class SimpleEntity : public Entity { public: SimpleEntity() { this-&gt;Class = "SimpleEntity"; } SimpleEntity(const SimpleEntity&amp; se) { this- &gt;Class = se.Class; } std::string virtual GetClass(std::string PreFix) { return Class + PreFix; } }; #include &lt;boost/python/module.hpp&gt; #include &lt;boost/python/def.hpp&gt; #include &lt;boost/python/args.hpp&gt; #include &lt;boost/python/class.hpp&gt; #include &lt;boost/python/overloads.hpp&gt; #include &lt;boost/python/call_method.hpp&gt; using namespace boost::python; std::string Test(Entity* e, std::string PreFix) { return e-&gt;GetClass(PreFix); } class EntityWrap : public Entity { public: EntityWrap(PyObject* self_) : self(self_) {} EntityWrap(PyObject* self_, const Entity&amp; e) : self(self_), Entity(e) {} std::string GetClass(std::string PreFix) { return call_method&lt;std::string&gt;(self, "GetClass", PreFix); } std::string default_GetClass( Entity&amp; e, std::string PreFix) { return e.Entity::GetClass(PreFix); } private: PyObject* self; }; class SimpleEntityWrap : public SimpleEntity { public: SimpleEntityWrap(PyObject* self_) : self(self_) {} SimpleEntityWrap(PyObject* self_, const SimpleEntity&amp; se) : self(self_), SimpleEntity(se) {} std::string GetClass(std::string PreFix) { return call_method&lt;std::string&gt;(self, "GetClass", PreFix); } std::string default_GetClass( SimpleEntity&amp; se, std::string PreFix) { return se.SimpleEntity::GetClass (PreFix); } private: PyObject* self; }; BOOST_PYTHON_MODULE(hello) { class_&lt;Entity, EntityWrap&gt;("Entity") .def(init&lt;const Entity&amp;&gt;()) .def("GetClass", &amp;EntityWrap::default_GetClass) .def_readwrite("Class", &amp;Entity::Class); ; class_&lt;SimpleEntity, SimpleEntityWrap, bases&lt;Entity&gt; &gt;("SimpleEntity") .def(init&lt;const SimpleEntity&amp;&gt;()) .def("GetClass", &amp;SimpleEntityWrap::default_GetClass) ; def("Test", Test); } Python Code: Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32 Type "copyright", "credits" or "license" for more information. IDLE 0.8 -- press F1 for help &gt;&gt;&gt; from hello import * &gt;&gt;&gt; class DerivedEntity(SimpleEntity): def __init__(self): SimpleEntity.Class = "DerivedEntity" def GetClass(self,x): return self.Class + x &gt;&gt;&gt; e = Entity() &gt;&gt;&gt; Test(e, " a test") Traceback (most recent call last): File "&lt;pyshell#4&gt;", line 1, in ? Test(e, " a test") TypeError: bad argument type for built-in operation &gt;&gt;&gt; s = SimpleEntity() &gt;&gt;&gt; Test(s, " a test") Traceback (most recent call last): File "&lt;pyshell#6&gt;", line 1, in ? Test(s, " a test") TypeError: bad argument type for built-in operation &gt;&gt;&gt; d = DerivedEntity() &gt;&gt;&gt; Test(d, " a test") Traceback (most recent call last): File "&lt;pyshell#8&gt;", line 1, in ? Test(d, " a test") TypeError: bad argument type for built-in operation &gt;&gt;&gt; e.Class 'Entity' &gt;&gt;&gt; e.GetClass(" a test") Traceback (most recent call last): File "&lt;pyshell#10&gt;", line 1, in ? e.GetClass(" a test") TypeError: bad argument type for built-in operation &gt;&gt;&gt; s.Class 'DerivedEntity' &gt;&gt;&gt; s.GetClass("a test") Traceback (most recent call last): File "&lt;pyshell#12&gt;", line 1, in ? s.GetClass("a test") TypeError: bad argument type for built-in operation &gt;&gt;&gt; d.Class 'DerivedEntity' &gt;&gt;&gt; d.GetClass(" a test") 'DerivedEntity a test' &gt;&gt;&gt; ------------------End Code --------------------------- Am I missing something? Any help would be appreciated. Thanks, Vince </pre> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/138 Trac 1.4.3 Joel de Guzman Tue, 25 Feb 2003 04:01:54 GMT <link>https://svn.boost.org/trac10/ticket/138#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/138#comment:1</guid> <description> <pre class="wiki">Logged In: YES user_id=237817 Hi Vince, The tutorial has been updated. There's a specific page now that focuses on virtual functions with default implementation. You can read it here: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/*checkout*/boost/boost/libs/python/doc/tutorial/doc/virtual_functions_with_default_implementations.html Attached is the corrected code. Most notably: std::string default_GetClass(std::string PreFix) { return Entity::GetClass(PreFix); } ... If you have to pass an object as the first argument, it has to be a static function. A non-static function will do. std::string default_GetClass(std::string PreFix) { return SimpleEntity::GetClass(PreFix); } ...Ditto. .def("GetClass", &amp;Entity::GetClass, &amp;EntityWrap::default_GetClass) ...See the tutorial link that I gave above. .def("GetClass", &amp;SimpleEntity::GetClass, &amp;SimpleEntityWrap::default_GetClass) ... Ditto Finally... &gt;&gt;&gt; class DerivedEntity(SimpleEntity): ... def __init__(self): ... SimpleEntity.Class = "DerivedEntity" ... def GetClass(self,x): ... return self.Class + x looks suspicious. Doesn't it need to __init__ the base class? See the attached corrections. Regards, -- Joel de Guzman joel at boost-consulting.com http://www.boost-consulting.com http://spirit.sf.net </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>nobody</dc:creator> <pubDate>Tue, 25 Feb 2003 21:16:23 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/138#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/138#comment:2</guid> <description> <pre class="wiki">Logged In: NO Thanks for the fix Joel, everything works as expected now. I really appreciate your prompt response. One last thing, I am assuming that this solution is only applicable to the version of boost currently in cvs? When I tried the same fix with version 1.29 it generates a compile error. Much Thanks, Vince The above mentioned error in case you weren't aware. C:\Documents and Settings\thomasinov\Desktop\boost_1_29_0 \boost\python\detail\de f_helper.hpp(131) : error C2440: 'return' : cannot convert from 'std::basic_stri ng&lt;_Elem,_Traits,_Ax&gt; ' to 'const char *' with [ _Elem=char, _Traits=std::char_traits&lt;char&gt;, _Ax=std::allocator&lt;char&gt; ] There is no context in which this conversion is possible C:\Documents and Settings\thomasinov\Desktop\boost_1_29_0\boost\python\d etail\def_helper.hpp(130) : while compiling class-template member function 'cons t char *boost::python::detail::def_helper&lt;T1,T2,T3&gt;::doc(void) const' with [ T1=std::basic_string&lt;char,std::char_traits&lt;char&gt;,std::allocator&lt;c har &gt;&gt; (__thiscall EntityWrap::* )(std::string), T2=boost::python::detail::not_specified, T3=boost::python::detail::not_specified ] C:\Documents and Settings\thomasinov\Desktop\boost_1_29_0\boost\python\c lass.hpp(362) : see reference to class template instantiation 'boost::python::de tail::def_helper&lt;T1,T2,T3&gt;' being compiled with [ T1=std::basic_string&lt;char,std::char_traits&lt;char&gt;,std::allocator&lt;c har &gt;&gt; (__thiscall EntityWrap::* )(std::string), T2=boost::python::detail::not_specified, T3=boost::python::detail::not_specified ] C:\Documents and Settings\thomasinov\Desktop\boost_1_29_0\boost\python\c lass.hpp(227) : see reference to function template instantiation 'void boost::py thon::class_&lt;T,X1,X2,X3&gt;::dispatch_def(const void *,const char *,std::basic_stri ng&lt;_Elem,_Traits,_Ax&gt; ,std::basic_string&lt;_Elem,_Traits,_Ax&gt; &amp; )' being compiled with [ T=Entity, X1=EntityWrap, X2=boost::python::detail::not_specified, X3=boost::python::detail::not_specified, _Elem=char, _Traits=std::char_traits&lt;char&gt;, _Ax=std::allocator&lt;char&gt; ] hello.cpp(141) : see reference to function template instantiation 'boost ::python::class_&lt;T,X1,X2,X3&gt;::self &amp;boost::python::class_&lt;T,X1,X2,X3&gt;::def(const char *,std::basic_string&lt;_Elem,_Traits,_Ax&gt; ,std::basic_string&lt;_Elem, _Traits,_A x&gt; &amp; )' being compiled with [ T=Entity, X1=EntityWrap, X2=boost::python::detail::not_specified, X3=boost::python::detail::not_specified, _Elem=char, _Traits=std::char_traits&lt;char&gt;, _Ax=std::allocator&lt;char&gt; ] </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>Joel de Guzman</dc:creator> <pubDate>Tue, 25 Feb 2003 21:49:31 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/138#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/138#comment:3</guid> <description> <pre class="wiki">Logged In: YES user_id=237817 Hi Vince, Yes, the solution requires the latest CVS code which is almost Boost 1.30.0 in just a few more days. Pardon me for not mentioning that. However, there is actually a 1.29.0 solution. See http://article.gmane.org/gmane.comp.python.c++/1861 for details. Cheers, -- Joel de Guzman joel at boost-consulting.com http://www.boost-consulting.com http://spirit.sf.net </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>david_abrahams</dc:creator> <pubDate>Wed, 13 Sep 2006 20:47:51 GMT</pubDate> <title>status changed https://svn.boost.org/trac10/ticket/138#comment:4 https://svn.boost.org/trac10/ticket/138#comment:4 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> </ul> Ticket