[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