00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 #ifndef BASE_PYOBJECTBASE_H
00024 #define BASE_PYOBJECTBASE_H
00025 
00026 
00027 
00028 
00029 #if defined (_POSIX_C_SOURCE)
00030 #   undef    _POSIX_C_SOURCE
00031 #endif
00032 #if defined (_XOPEN_SOURCE)
00033 #   undef    _XOPEN_SOURCE
00034 #endif
00035 
00036 
00037 #undef slots
00038 #   include <Python.h>
00039 #define slots
00040 #include <iostream>
00041 #include <bitset>
00042 
00043 #include <typeinfo>
00044 #include "Exception.h"
00045 #include <CXX/Objects.hxx>
00046 
00047 
00048 
00060 #define PYFUNCDEF_S(SFUNC)   static PyObject* SFUNC (PyObject *self,PyObject *args,PyObject *kwd);
00061 
00062 
00076 #define PYFUNCIMP_S(CLASS,SFUNC) PyObject* CLASS::SFUNC (PyObject *self,PyObject *args,PyObject *kwd)
00077 
00081 union PyType_Object {
00082     PyTypeObject *t;
00083     PyObject *o;
00084 };
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 namespace Base
00095 {
00096 
00097 inline int streq(const char *A, const char *B)  
00098 { return strcmp(A,B) == 0;};
00099 
00100 
00101 inline void Assert(int expr, char *msg)         
00102 {
00103     if (!expr) 
00104     {
00105       fprintf(stderr, "%s\n", msg);
00106       exit(-1);
00107     };
00108 }
00109 
00110 }
00111 
00112 
00113 
00114 
00115 
00117 #define Py_NEWARGS 1
00119 #define Py_Return Py_INCREF(Py_None); return Py_None;
00121 #define Py_Error(E, M)   {PyErr_SetString(E, M); return NULL;}
00123 #define Py_Try(F) {if (!(F)) return NULL;}
00125 #define Py_Assert(A,E,M) {if (!(A)) {PyErr_SetString(E, M); return NULL;}}
00126 
00127 
00129 typedef PyTypeObject * PyParentObject;
00130 
00131 
00133 #define Py_Header                                           \
00134 public:                                                     \
00135     static PyTypeObject   Type;                             \
00136     static PyMethodDef    Methods[];                        \
00137     static PyParentObject Parents[];                        \
00138     virtual PyTypeObject *GetType(void) {return &Type;};    \
00139     virtual PyParentObject *GetParents(void) {return Parents;}
00140 
00145 #define _getattr_up(Parent)                                 \
00146 {                                                           \
00147     PyObject *rvalue = Py_FindMethod(Methods, this, attr);  \
00148     if (rvalue == NULL)                                     \
00149     {                                                       \
00150         PyErr_Clear();                                      \
00151         return Parent::_getattr(attr);                      \
00152     }                                                       \
00153     else                                                    \
00154         return rvalue;                                      \
00155 } 
00156 
00157 
00158 
00159 
00160 
00161 namespace Base
00162 {
00163 
00164 
00186 class BaseExport PyObjectBase : public PyObject 
00187 {
00192     Py_Header;
00193 
00194 protected:
00196     virtual ~PyObjectBase();
00197 
00198 public:  
00203     PyObjectBase(void*, PyTypeObject *T);
00205     static void PyDestructor(PyObject *P)   
00206     {  delete ((PyObjectBase *) P);  }
00208     PyObjectBase* IncRef(void) {Py_INCREF(this);return this;}
00210     PyObjectBase* DecRef(void) {Py_DECREF(this);return this;}
00211 
00221     virtual PyObject *_getattr(char *attr);
00223     static  PyObject *__getattr(PyObject * PyObj, char *attr);
00224 
00231     virtual int _setattr(char *attr, PyObject *value);    
00233     static  int __setattr(PyObject *PyObj, char *attr, PyObject *value);
00234 
00249     virtual PyObject *_repr(void);
00251     static  PyObject *__repr(PyObject *PyObj)   {
00252         if (!((PyObjectBase*) PyObj)->isValid()){
00253             PyErr_Format(PyExc_ReferenceError, "Cannot print representation of deleted object");
00254             return NULL;
00255         }
00256         return ((PyObjectBase*) PyObj)->_repr();
00257     }
00258 
00263     virtual int PyInit(PyObject* , PyObject* )
00264     {
00265         return 0;
00266     }
00268     static  int __PyInit(PyObject* self, PyObject* args, PyObject* kwd)
00269     {
00270         return ((PyObjectBase*) self)->PyInit(args, kwd);
00271     }
00272 
00273     void setInvalid() { 
00274         
00275         StatusBits.reset(0);
00276         _pcTwinPointer = 0;
00277     }
00278 
00279     bool isValid() {
00280         return StatusBits.test(0);
00281     }
00282 
00283     void setConst() {
00284         
00285         StatusBits.set(1);
00286     }
00287 
00288     bool isConst() {
00289         return StatusBits.test(1);
00290     }
00291 
00292     void setAttributeOf(const char* attr, const PyObjectBase* par);
00293     void startNotify();
00294 
00295     typedef void* PointerType ;
00296 
00297 protected:
00298     std::bitset<32> StatusBits;
00300     void * _pcTwinPointer;
00301     PyObjectBase* parent;
00302     char* attribute;
00303 };
00304 
00305 
00306 
00307 
00326 #define PYFUNCDEF_D(CLASS,DFUNC)        PyObject * DFUNC (PyObject *args);  \
00327 static PyObject * s##DFUNC (PyObject *self, PyObject *args, PyObject * ){return (( CLASS *)self)-> DFUNC (args);};
00328 
00341 #define PYFUNCIMP_D(CLASS,DFUNC) PyObject* CLASS::DFUNC (PyObject *args)
00342 
00343 
00344 
00369 #define PYMETHODEDEF(FUNC)      {"" #FUNC "",(PyCFunction) s##FUNC,Py_NEWARGS},
00370 
00371 
00372 
00410 #define PY_TRY  try 
00411 
00412 #ifndef DONT_CATCH_CXX_EXCEPTIONS 
00414 #  define PY_CATCH catch(Base::Exception &e)                        \
00415     {                                                               \
00416         std::string str;                                            \
00417         str += "FreeCAD exception thrown (";                        \
00418         str += e.what();                                            \
00419         str += ")";                                                 \
00420         e.ReportException();                                        \
00421         Py_Error(PyExc_Exception,str.c_str());                      \
00422     }                                                               \
00423     catch(std::exception &e)                                        \
00424     {                                                               \
00425         std::string str;                                            \
00426         str += "STL exception thrown (";                            \
00427         str += e.what();                                            \
00428         str += ")";                                                 \
00429         Base::Console().Error(str.c_str());                         \
00430         Py_Error(PyExc_Exception,str.c_str());                      \
00431     }                                                               \
00432     catch(const Py::Exception&)                                     \
00433     {                                                               \
00434         return NULL;                                                \
00435     }                                                               \
00436     catch(const char *e)                                            \
00437     {                                                               \
00438         Py_Error(PyExc_Exception,e);                                \
00439     }                                                               \
00440     catch(...)                                                      \
00441     {                                                               \
00442         Py_Error(PyExc_Exception,"Unknown C++ exception");          \
00443     }
00444 
00445 #else
00447 #  define PY_CATCH catch(Base::Exception &e)                        \
00448     {                                                               \
00449         std::string str;                                            \
00450         str += "FreeCAD exception thrown (";                        \
00451         str += e.what();                                            \
00452         str += ")";                                                 \
00453         e.ReportException();                                        \
00454         Py_Error(PyExc_Exception,str.c_str());                      \
00455     }                                                               \
00456     catch(std::exception &e)                                        \
00457     {                                                               \
00458         std::string str;                                            \
00459         str += "STL exception thrown (";                            \
00460         str += e.what();                                            \
00461         str += ")";                                                 \
00462         Base::Console().Error(str.c_str());                         \
00463         Py_Error(PyExc_Exception,str.c_str());                      \
00464     }                                                               \
00465     catch(const Py::Exception&)                                     \
00466     {                                                               \
00467         return NULL;                                                \
00468     }                                                               \
00469     catch(const char *e)                                            \
00470     {                                                               \
00471         Py_Error(PyExc_Exception,e);                                \
00472     }
00473 
00474 #endif  // DONT_CATCH_CXX_EXCEPTIONS
00475 
00477 #define PARENTSBasePyObjectBase &Base::PyObjectBase::Type,NULL
00478 
00483 inline PyObject * PyAsUnicodeObject(const char *str)
00484 {
00485     
00486     PyObject *p = PyUnicode_DecodeUTF8(str,strlen(str),0);
00487     if(!p)
00488         throw Base::Exception("UTF8 conversion failure at PyAsUnicodeString()");
00489     return p;
00490 }
00491 
00492 inline PyObject * PyAsUnicodeObject(const std::string &str)
00493 {
00494     return PyAsUnicodeObject(str.c_str());
00495 }
00496 
00497 
00498 } 
00499 
00500 
00501 #endif // BASE_PYOBJECTBASE_H