[C++-SIG] design question - python extensions in C++

Paul F. Dubois dubois1 at llnl.gov
Sun Feb 6 07:17:45 CET 2000


David Abrahams and Barry Scott have also done quite a lot of improvement in
this area. I don't have time right now to get into this but you should
compare notes with them. There is some concern about recent changes to the
C++ standard that they can brief you on.

As I said in my talk at IPC8 I am looking to pass CXX off to some new
caretakers since my current work does not involve C++.

In the new approach, you inherit from PyObject to make a new object type.

I liked what I did on the CXX_Objects side but was not satisfied with the
extension side, so I'm glad that others have taken up the call.

> -----Original Message-----
> From: c++-sig-admin at python.org [mailto:c++-sig-admin at python.org]On
> Behalf Of Brad Venner
> Sent: Friday, February 08, 1980 12:14 PM
> To: c++-sig at python.org
> Subject: [C++-SIG] design question - python extensions in C++
>
>
> Greetings,
>
> I would like to get some feedback regarding some design decisions on
> some work I have done on C++ extensions.
>
> The design philosopy in CXX_Extensions by P. Dubois is to create a
> unique type object for each C++ class.  This is basically the approach
> used in CPython, where each python type has an associated type object.
> These type objects are created through the use of a templated class in
> which the class being defined is given as an argument to the template
> class.  In my use of CXX, I found myself writing very similar code for
> each class I derived.  For example, each class needed a getattr
> function that was identical to all the other getattr functions in
> every class.  This can partially be addressed by creating an
> intermediate class that provides a default implementation of some of
> these common functions.
>
> In several posts in December, 1999, John Skaller proposed and outlined
> in detail an approach in which there is a single python type object
> that parallels a single C++ abstract base class.  Since fools rush in
> where angels fear to tread, I have implemented some of the ideas
> outlined in J. Skaller's posts.  The basic idea of the code is as
> follows:
>
> class CppPyObject: public PyObject {
>   public:
>     virtual int print() {throw TypeError("unimplemented_method");}
> }
> class CppPyType {
>   // code to initialize static _typeobject struct
>   PyTypeObject * type_object();
>   public:
>     static bool check(PyObject * pyob)
>       { return pyob && pyob->ob_type==type_object(); }
>     static int print(PyObject* pyob) {
>       try {
>  if(check(pyob)) {
>           static_cast<CppPyObject*>(pyob)->print();
>    return 0;
>  }
>         // error handling & return
>     }
> }
> CppPyType& cpp_type() {
>   // singleton pattern
>   static ObjectType type;
>   return type;
> }
> class MyObject: public CppPyObject {
> private:
>   MyObject() {
>     ob_refcnt = 1;
>     ob_type=cpp_type().type_object();
>   }
> public:
>   PyObject* create(PyObject*, PyObject*);
>   virtual int print() {cout << "It's alive";}
> }
>
> This approach seems to work, and reduces the amount of work required to
> implement the virtual functions, since Python-specific stuff can be
> moved into the default function, including error checking.  As
> discussed by Skaller, methods can be added by overloading the virtual
> getattr function in the concrete class.  Taking Skaller's hint, I used
> stl::map<> to implement the method tables.
>
> There are several design decisions now that I would like to get
> feedback on.  One problem I'm running into now is how to safely
> convert PyObject*'s to the appropriate and specific C++
> implementation.  In the CXX approach, there would be a static function
> MyObject::check.  Again, this is similar to the CPython approach,
> which checks to see if the address of the type object since one-to-one
> correspondence with the type object.  In the Skaller approach, the
> type-checking routine has to be (can be?) implemented within the C++
> iterface class CppPyObject.  The design I am attempting is to use
> class-specific identifiers (static strings) in creation-type classes
> and the use a virtual "check" function to perform type checking using
> string comparison.  For example,
>
> PyObject* function(PyObject *self, PyObject* args) {
>   Tuple a(args);
>   // check length
>   PyObject* arg1 = a[0].ptr();
>   ObjectProtocol * arg1 = static_cast<ObjectProtocol*>(arg1);
>   if(arg1->check("MyObject"))

>     MyObject * myob = static_cast<MyObject*>(arg1);
>     // do useful stuff
>   }
>   else throw TypeError("Function requires MyObject argument");
> }
>
> Does anyone have a better idea or approach that I should consider.
>
> A second problem is how to check for to see if a PyObject* implements
> a particular Python/C++ interface.  It would be nice to write C++
> functions that did not require conversion to a specific creation-type
> but instead could check to see if a creation-type implemented a
> particular interface, and then cast the PyObject* to a pointer to the
> interface.  Python checks for it's interface "types" (number,
> sequence, mapping) by checking for a null-pointer in the type object.
> A C++ equivalent is needed but I don't really see how to do it.
>
> Anyway, I appreciate any feedback on these or other issues.  My e-mail
> address at work is venner.brad at epa.gov, at home is
> vennerbc at mindspring.com.
>
>
>
>
>
> _______________________________________________
> C++-SIG maillist  -  C++-SIG at python.org
> http://www.python.org/mailman/listinfo/c++-sig
>





More information about the Cplusplus-sig mailing list