[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