[C++-SIG] just to introduce me and some comments

Barry Scott barry at scottb.demon.co.uk
Mon May 22 21:22:12 CEST 2000


I realise I'm late in answer your message...

Can I assume that the current sources in SourceForge address all your issues
with CXX. If not please let me know what is missing.

I think your comments are on a version of CXX before I contributed code.

		Barry

> -----Original Message-----
> From: c++-sig-admin at python.org [mailto:c++-sig-admin at python.org]On
> Behalf Of Thomas Malik
> Sent: 03 March 2000 23:53
> To: c++-sig at python.org
> Subject: [C++-SIG] just to introduce me and some comments
> 
> 
> Hello, since i am new to this group, ok, i'm Thomas.
> I've taken the CXX package 3 months ago (don't know which version it was)
> and changed many things to suit my needs. My requirements were:
> - simple, homogeneous look of my wrapper classes, since i had to write a
> whole lot of them
> - use of inheritance in the wrapper classes, since the class library i had
> to incorporate into python, had it, and i didn't want to do mass copies of
> source code (every base class method in every subclass)
> - the whole thing has to run rock solid, since it's going to be used for
> interconnecting stock trading applications in a financial institute.
> - I wanted to rely on C++ exceptions as error notification mechanism.
> 
> What i did:
> I moved the inheritance of the PythonExtension template from PyObject 'one
> level up', by introducing an intermediate class
> CXXPyObject with a virtual destructor:
> 
> // The purpose of this is only to get a virtual destructor into a PyObject
> and to
> // be able to use dynamic_cast on it. PythonExtension inherits virtually
> from this.
> class CXXPyObject : public PyObject {
>   protected:
>     CXXPyObject() {}
>   public:
>     virtual ~CXXPyObject() {}
> };
> 
> CXXObject is a virtual base class for PythonExtension.
> Now, i can use dynamic_cast even in situations, where i inherit from
> PythonExtension multiple times, see below.
> Another thing i changed was to eliminate the template argument from
> PythonType. It's only purpose was to get the Object size, but you can pass
> this easily as a constructor argument, or even pass the size as a template
> argument. The downside is, you have to keep PythonExtension as a template
> class, since the constructor cannot determine the object size at
> construction time.
> 
> To do easy, safe casting in the static member functions (Python entry
> points) i introduced a template function
> T python_cast<class T>(PyObject *). This does first a static_cast to the
> CXXObject*, and then a dynamic_cast to the object i'm actually in. Of
> course, this does NOT lead me magically into the paths of the right member
> functions of the right class, but i'm using dynamic_cast & the virtual
> function table for type checking, which gives me a fairly efficient type
> safe conversion.
> 
> template<class T>
> T python_cast(PyObject *p) {
>   T result = dynamic_cast<T>(static_cast< CXXPyObject* >(p));
>   if (result == NULL) {
>     cerr << "!shit! cast failed!" << endl;
>     throw bad_cast();
>   }
>   return result;
> }
> 
> Lastly, i've added some 'standard' functionality into PythonType &
> PythonExtension, such as str(), repr(), getattr().
> I strictly obey the following rule in my source:
> - Python entry points always have a name starting with 's_' (such as
> s_str(PyObject* self, PyObject* a)  )
> - the first lines look like
> MyClassName* self=python_cast<MyClassName*>(s); // looks damn familiar,
> doesn't it ?
> Tuple args(a);
> 
> so, here's some chunk out of the PythonExtension template:
> // since CXXPyObject is a virtual Baseclass of PythonExtension, you can
> // safely use multiple inheritance with the following Scheme:
> // class A : public PythonExtension<A> {
> // };
> // class B : public A, public PythonExtension<B> {
> // }
> //
> // in A's an B's methods you may use the python_cast<A*>() thing below
> // to get a A* or B* out of a PyObject *
> template<class T>
> class PythonExtension: public virtual CXXPyObject
> {
>   private:
>     static void extension_object_deallocator(PyObject* t) {
>       CXXPyObject* o=static_cast<CXXPyObject*>(t);
>       delete o;
>       // delete t;
>     }
> 
>     explicit PythonExtension(const PythonExtension<T>& other);
>     void operator=(const PythonExtension<T>& rhs);
>   protected:
>     explicit PythonExtension() {
>       ob_refcnt = 1;
>       ob_type = type_object();
>     }
>   public:
>     virtual ~PythonExtension() {}
> 
>     static PythonType& behaviors() {
>       static PythonType* p;
>       if(!p) {
>          p = new PythonType(sizeof(T));
>          p->dealloc(extension_object_deallocator);
>          p->str(s_str);
>          p->repr(s_repr);
>       }
> ...
> }
> 
> If someone's interested; i can send the whole story(code).
> BTW, I've also implemented some huge macros for easy (and safe!) use of
> exceptions within C++ Modules. Note that you CAN'T throw exceptions
> 'through' the python interpreter. Consider this:
> 
> PyObject* mainEventLoop()
> {
>     PyObject* o=someObject;
>     try {
>         while (...)
>             // some crufty event magic going on
>             if (eventOccured())
>                 Py_CallMethod(o,"crashbang",...);
>     }
>     catch (const Exception&) {
>     }
> }
> 
> and 'crashbang()' calls a C++ method from within your module, which throws
> an exception. My experience was that the process will go wreck, with the
> default execption handler aborting the program. What i did is to write a
> macro to catch these exceptions and to return Null instead.
> 
> Ok, that's it for today. Comments are welcome.
> 
> Thomas Malik
> 
> 
> 
> 
> _______________________________________________
> C++-SIG maillist  -  C++-SIG at python.org
> http://www.python.org/mailman/listinfo/c++-sig
> 




More information about the Cplusplus-sig mailing list