ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> cpp-sig
cpp-sig
[C++-sig] Support for virtual functions with default implementations
by David Abrahams other posts by this author
Nov 27 2002 6:57AM messages near this date
Re: [C++-sig] Conversion from python objects to c++ objects for argument passing | [C++-sig] Boost.Python Function overload resolution order
Some of you have been struggling with a supposed inability of
Boost.Python v2 to correctly expose virtual functions with default
implementations. You can read all about the nitty-gritty details at:

http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/*checkout*/boost/boost/libs/python/doc/polymo
rphism.txt

The bottom line, when exposing a class B with its "callback" class
Bcb...

   struct B
   { 
      virtual std::string f() { return "B"; }
   };

   struct BWrap : B
   { 
      BWrap(PyObject* self) : m_self(self) {}

      virtual std::string f()
      { 
         return call_method<std::string> (m_self, "f");
      }

      std::string f_default()
      {
         return B::f();
      }

      PyObject* m_self;
   };

...turns out to be that sometimes, from Python, B.f() must invoke B::f
virtually (e.g. when the Python object actually holds a [smart]
pointer to some C++ class derived from B), and sometimes it must
invoke BWrap::f_default, which invokes the actual B::f defined in B.

Well, after several weeks of working on a complicated solution to this
problem, I had an Aha! moment, and realized that we already had the
capability!** The key is simply to expose your class like this:

   class_<B, BWrap      // or, e.g., shared_ptr<BWrap> 
          > ("B")
       .def("f", &B::f)             // dispatch function
       .def("f", &BWrap::f_default) // default implementation
       ;

That's it! Because later def() overloads get precedence, your default
implementation will be used if the Python object actually contains a
BWrap object. Otherwise, it will call B::f virtually.

Issues: 
   1. f_default MUST be a member function of BWrap, or take a BWrap&
      first argument

   2. You MUST def() f_default second.

Failure to get either of these right will result in crashes or other
runtime failures.

I have just checked in changes which allow you to supply your default
implementation in the .def() invocation:

      .def("f", &B::f, &BWrap::f_default)

This version will catch those potential errors at
compile-time. However, the other version should work fine with the
Boost 1.29.0 release.

-Dave

**Don't worry, the weeks weren't a complete waste; the code got a lot
  cleaner as I refactored things.

-- 
                       David Abrahams
   dave@[...].com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution


_______________________________________________
C++-sig mailing list
C++-sig@[...].org
http://mail.python.org/mailman/listinfo/c++-sig

Privacy Policy | Email Opt-out | Feedback | Syndication
© ActiveState Software Inc. All rights reserved