library of assembled shared sources

http://lass.cocamware.com

pyobject_plus.h

Go to the documentation of this file.
00001 /** @file
00002  *  @author Bram de Greve (bramz@users.sourceforge.net)
00003  *  @author Tom De Muer (tomdemuer@users.sourceforge.net)
00004  *
00005  *  *** BEGIN LICENSE INFORMATION ***
00006  *  
00007  *  The contents of this file are subject to the Common Public Attribution License 
00008  *  Version 1.0 (the "License"); you may not use this file except in compliance with 
00009  *  the License. You may obtain a copy of the License at 
00010  *  http://lass.sourceforge.net/cpal-license. The License is based on the 
00011  *  Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 
00012  *  use of software over a computer network and provide for limited attribution for 
00013  *  the Original Developer. In addition, Exhibit A has been modified to be consistent 
00014  *  with Exhibit B.
00015  *  
00016  *  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 
00017  *  WARRANTY OF ANY KIND, either express or implied. See the License for the specific 
00018  *  language governing rights and limitations under the License.
00019  *  
00020  *  The Original Code is LASS - Library of Assembled Shared Sources.
00021  *  
00022  *  The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
00023  *  The Original Developer is the Initial Developer.
00024  *  
00025  *  All portions of the code written by the Initial Developer are:
00026  *  Copyright (C) 2004-2007 the Initial Developer.
00027  *  All Rights Reserved.
00028  *  
00029  *  Contributor(s):
00030  *
00031  *  Alternatively, the contents of this file may be used under the terms of the 
00032  *  GNU General Public License Version 2 or later (the GPL), in which case the 
00033  *  provisions of GPL are applicable instead of those above.  If you wish to allow use
00034  *  of your version of this file only under the terms of the GPL and not to allow 
00035  *  others to use your version of this file under the CPAL, indicate your decision by 
00036  *  deleting the provisions above and replace them with the notice and other 
00037  *  provisions required by the GPL License. If you do not delete the provisions above,
00038  *  a recipient may use your version of this file under either the CPAL or the GPL.
00039  *  
00040  *  *** END LICENSE INFORMATION ***
00041  */
00042 
00043 /** @defgroup Python
00044  *  @brief interface library to Python
00045  */
00046 
00047 #ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_PYOBJECT_PLUS_H
00048 #define LASS_GUARDIAN_OF_INCLUSION_UTIL_PYOBJECT_PLUS_H
00049 
00050 #include "util_common.h"
00051 #include "singleton.h"
00052 
00053 // Python.h is a bit blunt in (re)defining _POSIX_C_SOURCE causing a nice warning.
00054 // Undefing it before including Python.h will suppress that warning.
00055 // Remove this once Python plays nice again. 
00056 // [Bramz]
00057 #if defined(_POSIX_C_SOURCE)
00058 #   undef _POSIX_C_SOURCE
00059 #endif
00060 
00061 #if defined(_DEBUG) && LASS_PYTHON_HAS_DEBUG_BUILD == 0
00062 #   undef _DEBUG
00063 #   include "Python.h"
00064 #   define _DEBUG
00065 #else
00066 #   include "Python.h"
00067 #endif
00068 
00069 #ifndef PySequence_ITEM
00070 #   define PySequence_ITEM(o, i) PySequence_GetItem(o, i)
00071 #endif
00072 
00073 #ifndef PySequence_Fast_ITEMS
00074 #   define PySequence_Fast_ITEMS(o) \
00075     (PyTuple_Check(o) ? ((PyTupleObject *)(o))->ob_item : ((PyListObject *)(o))->ob_item)
00076 #endif
00077 
00078 #ifndef Py_RETURN_FALSE
00079 #   define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
00080 #endif
00081 
00082 #ifndef Py_RETURN_TRUE
00083 #   define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
00084 #endif
00085 
00086 #ifndef Py_RETURN_NONE
00087 #   define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
00088 #endif
00089 
00090 #if (PY_VERSION_HEX < 0x02050000)
00091 #   define Py_ssize_t int
00092 #   define lenfunc inquiry
00093 #   define ssizeargfunc intargfunc
00094 #   define ssizessizeargfunc intintargfunc
00095 #   define ssizeobjargproc intobjargproc
00096 #   define ssizessizeobjargproc intintobjargproc
00097 #endif
00098 
00099 #include "../meta/is_derived.h"
00100 #include "../meta/select.h"
00101 #include "shared_ptr.h"
00102 #include "string_cast.h"
00103 #include "thread.h"
00104 #include <cstdlib>
00105 
00106 #if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC
00107 #   pragma warning(push)
00108 #   pragma warning(disable: 4267) // conversion from 'size_t' to 'unsigned int', possible loss of data
00109 #endif
00110 
00111 /** @internal
00112  *  This macro is only used in the PyObjectPlus class and is for internal LASS
00113  *  use.  Do not use in custom objects... DON'T!
00114  */
00115 #define PY_HEADER_INTERNAL \
00116     public: \
00117         static PyTypeObject   _lassPyType; \
00118         static ::std::vector<PyMethodDef>    _lassPyMethods; \
00119         static ::std::vector<PyGetSetDef>    _lassPyGetSetters; \
00120         virtual PyTypeObject *_lassPyGetType(void) const {return &_lassPyType;};\
00121     private:
00122 
00123 /** @ingroup Python
00124  *  Place as first line of your Pythonized class.    
00125  *
00126  *  For @a t_parentClass use the C++ class from which you wish the python object inherits.  
00127  *  @a t_parentClass must also be a Pythonized class or use lass::python::PyObjectPlus as default.
00128  *
00129  *   @remark Any declarations coming after this macro are private!
00130  */
00131 #define PY_HEADER( t_parentClass ) \
00132     public: \
00133         typedef t_parentClass _lassPyParentType;\
00134         static PyTypeObject _lassPyType; \
00135         static ::std::vector<PyMethodDef> _lassPyMethods; \
00136         static ::std::vector<PyGetSetDef> _lassPyGetSetters; \
00137         static ::lass::python::impl::TStaticMembers _lassPyStatics; \
00138         static ::lass::python::impl::TCompareFuncs _lassPyCompareFuncs;\
00139         virtual PyTypeObject* _lassPyGetType(void) const {return &_lassPyType;};\
00140         static PyTypeObject* _lassPyGetParentType(void)\
00141         {\
00142             return &_lassPyParentType::_lassPyType != &::lass::python::PyObjectPlus::_lassPyType ?\
00143                 &_lassPyParentType::_lassPyType : &PyBaseObject_Type;\
00144         }\
00145     private:
00146 
00147 namespace lass
00148 {
00149 namespace python
00150 {
00151 
00152 struct Caster
00153 {
00154 };
00155 
00156 template<typename T>
00157 struct IsACaster
00158 {
00159     typedef lass::meta::False TValue;
00160 };
00161 template <typename T>
00162 struct NoCast : public Caster
00163 {
00164     typedef T TSelf;
00165     typedef T TTarget;
00166     static TTarget cast(TSelf iArg) { return iArg; }
00167 };
00168 template <>
00169 struct NoCast<void> : public Caster
00170 {
00171     typedef void TSelf;
00172     typedef void TTarget;
00173     static TTarget cast(void) {}
00174 };
00175 
00176 ////
00177 template <typename T>
00178 struct PointerCast : public Caster
00179 {
00180     typedef T TSelf;
00181     typedef T* TPointer;
00182     typedef TPointer TTarget;
00183     static TSelf cast(TTarget iArg) { return *iArg; }
00184 };
00185 
00186 template<typename T>
00187 struct PointerCast<T&> : public Caster
00188 {
00189     typedef T& TSelf;
00190     typedef T* TPointer;
00191     typedef TPointer TTarget;
00192     static TSelf cast(TTarget iArg) { return *iArg; }
00193 };
00194 template<typename T>
00195 struct PointerCast<const T&> : public Caster
00196 {
00197     typedef T& TSelf;
00198     typedef T* TPointer;
00199     typedef TPointer TTarget;
00200     static TSelf cast(TTarget iArg) { return *iArg; }
00201 };
00202 template<typename T>
00203 struct PointerCast<T*> : public Caster
00204 {
00205     typedef T* TSelf;
00206     typedef T* TPointer;
00207     typedef TPointer TTarget;
00208     static TSelf cast(TTarget iArg) { return iArg; }
00209 };
00210 template<typename T>
00211 struct PointerCast<const T*> : public Caster
00212 {
00213     typedef const T* TSelf;
00214     typedef const T* TPointer;
00215     typedef TPointer TTarget;
00216     static TSelf cast(TTarget iArg) { return iArg; }
00217 };
00218 
00219 ////
00220  
00221 template <typename T>
00222 struct CopyCast : public Caster
00223 {
00224     typedef T TSelf;
00225     typedef T TCopy;
00226     typedef TCopy TTarget;
00227     static TSelf cast(TTarget iArg) { return TSelf(iArg); }
00228 };
00229 
00230 template<typename T>
00231 struct CopyCast<T&> : public Caster
00232 {
00233     typedef T& TSelf;
00234     typedef T TCopy;
00235     typedef TCopy TTarget;
00236     static TSelf cast(TTarget iArg) { return TSelf(iArg); }
00237 };
00238 template<typename T>
00239 struct CopyCast<const T&> : public Caster
00240 {
00241     typedef T& TSelf;
00242     typedef T TCopy;
00243     typedef TCopy TTarget;
00244     static TSelf cast(TTarget iArg) { return TSelf(iArg); }
00245 };
00246 template<typename T>
00247 struct CopyCast<T*> : public Caster
00248 {
00249     typedef T* TSelf;
00250     typedef T TCopy;
00251     typedef TCopy TTarget;
00252 };
00253 template<typename T>
00254 struct CopyCast<const T*> : public Caster
00255 {
00256     typedef const T* TSelf;
00257     typedef const T TCopy;
00258     typedef TCopy TTarget;
00259 };
00260 /////////
00261 template<typename T>
00262 struct IsACaster<PointerCast<T> >
00263 {
00264     typedef lass::meta::True TValue;
00265 };
00266 template<typename T>
00267 struct IsACaster<CopyCast<T> >
00268 {
00269     typedef lass::meta::True TValue;
00270 };
00271 
00272 template< typename T>
00273 struct OwnerCaster
00274 {
00275     typedef typename lass::meta::Select< typename IsACaster<T>::TValue , T, NoCast<T> >::Type TCaster;
00276 };
00277 
00278 }
00279 }
00280 
00281 
00282 namespace lass
00283 {
00284     namespace python
00285     {
00286         /** PyExportTraits.  A traits class that replaces the now deprecated pyBuildSimpleObject functionality.
00287         *   Reason is to support the two-phase name lookup during template instantiation. (gcc >=3.4 )
00288         */
00289         template<typename T>
00290         struct PyExportTraits
00291         {
00292             //static PyObject* build(const T& it) { Py_XINCREF(Py_None);  return Py_None; }
00293             //static int get(PyObject* iObject, T& ot) { return 1; } // probably should set an exception to match "UnImplemented" 
00294         };
00295         // a utility macro to easen the transition to the template based infrastructure
00296         #define PYEXPORTTRAITS_USINGDEPRECATED( t_basicType )   \
00297         template<>\
00298         struct PyExportTraits< t_basicType >\
00299         {\
00300             static PyObject* build(const t_basicType & iv) { return pyBuildSimpleObject_deprecated(iv); }\
00301             static int get(PyObject* iv, t_basicType & ov) { return pyGetSimpleObject_deprecated(iv,ov); }\
00302         };\
00303 
00304         #define PYEXPORTTRAITS_USINGDEPRECATED_TEMPL( t_basicType ) \
00305         template< typename T >\
00306         struct PyExportTraits< t_basicType< T > >\
00307         {\
00308             static PyObject* build(const t_basicType< T > & iv) { return pyBuildSimpleObject_deprecated(iv); }\
00309             static int get(PyObject* iv, t_basicType< T > & ov) { return pyGetSimpleObject_deprecated(iv,ov); }\
00310         };
00311         #define PYEXPORTTRAITS_USINGDEPRECATED_TEMPL_2( t_basicType )   \
00312         template< typename T, typename U >\
00313         struct PyExportTraits< t_basicType< T, U > >\
00314         {\
00315             static PyObject* build(const t_basicType< T, U > & iv) { return pyBuildSimpleObject_deprecated(iv); }\
00316             static int get(PyObject* iv, t_basicType< T, U> & ov) { return pyGetSimpleObject_deprecated(iv,ov); }\
00317         };
00318         #define PYEXPORTTRAITS_USINGDEPRECATED_TEMPL_3( t_basicType )   \
00319         template< typename T, typename U, typename V >\
00320         struct PyExportTraits< t_basicType< T, U, V > >\
00321         {\
00322             static PyObject* build(const t_basicType< T, U, V > & iv) { return pyBuildSimpleObject_deprecated(iv); }\
00323             static int get(PyObject* iv, t_basicType< T, U, V   > & ov) { return pyGetSimpleObject_deprecated(iv,ov); }\
00324         };
00325         #define PYEXPORTTRAITS_USINGDEPRECATED_TEMPL_4( t_basicType )   \
00326         template< typename T, typename U, typename V, typename W >\
00327         struct PyExportTraits< t_basicType< T, U, V, W > >\
00328         {\
00329             static PyObject* build(const t_basicType< T, U, V, W > & iv) { return pyBuildSimpleObject_deprecated(iv); }\
00330             static int get(PyObject* iv, t_basicType< T, U, V, W > & ov) { return pyGetSimpleObject_deprecated(iv,ov); }\
00331         };
00332 
00333         /** @ingroup Python
00334          */
00335         template<typename T>
00336         PyObject* pyBuildSimpleObject(T& iV)
00337         {
00338             return PyExportTraits<T>::build(iV);
00339         }
00340 
00341         /** @ingroup Python
00342          */
00343         template<typename T>
00344         PyObject* pyBuildSimpleObject(const T& iV)
00345         {
00346             return PyExportTraits<T>::build(iV);
00347         }
00348 
00349         /** @ingroup Python
00350          */
00351         template<typename T>
00352         PyObject* pyBuildSimpleObject(std::auto_ptr<T> iV)
00353         {
00354             return PyExportTraits< std::auto_ptr<T> >::build(iV);
00355         }
00356 
00357         /** @ingroup Python
00358          */
00359         template<typename T>
00360         int pyGetSimpleObject(PyObject* iV, T& oV)
00361         {
00362             return PyExportTraits<T>::get(iV,oV);
00363         }
00364 
00365         /** Helper to specialise PyExportTraits for enumerations.
00366          *  @ingroup Python
00367          *
00368          *  When you want to export enumeration types, you need to specialize PyExportTraits for it.
00369          *  This structure will help you
00370          *
00371          *  @code
00372          *  enum MyEnumeration { meFoo, meBar, meFuz };
00373          *  namespace lass
00374          *  {
00375          *  namespace python
00376          *  {
00377          *  template <> struct PyExportTraits<MyEnumeration>: public PyExportTraitsEnum<MyEnumeration> {};
00378          *  }
00379          *  }
00380          *  @endcode
00381          */
00382         template <typename EnumType, typename IntegerType = long>
00383         struct PyExportTraitsEnum
00384         {
00385             static PyObject* build(const EnumType iv) 
00386             { 
00387                 return pyBuildSimpleObject(static_cast<IntegerType>(iv));
00388             }
00389             static int get(PyObject* iv, EnumType& ov) 
00390             { 
00391                 IntegerType temp;
00392                 if (pyGetSimpleObject(iv, temp) != 0)
00393                 {
00394                     return 1;
00395                 }
00396                 ov = static_cast<EnumType>(temp);
00397                 return 0;
00398             }
00399         };
00400 
00401         /** PyObjectPlus.  Base class for pythonable objects.
00402         *   @ingroup Python
00403         *   @author Tom De Muer
00404         *   @date 2003
00405         *   Usage:
00406         *   The usage will be given by providing an example.  See the test case and look
00407         *   for the files bar.h and bar.cpp.
00408         */
00409         class LASS_DLL PyObjectPlus :
00410             public PyObject
00411         {
00412             PY_HEADER_INTERNAL;
00413         public:
00414             typedef void TCppClass;
00415             PyObjectPlus(); 
00416             virtual ~PyObjectPlus();
00417             virtual std::string doPyRepr(void) { return std::string(ob_type->tp_name) + " object at " + util::stringCast<std::string>(this); }
00418             virtual std::string doPyStr(void) { return std::string(ob_type->tp_name) + " object string at " + util::stringCast<std::string>(this); }
00419 
00420         protected:
00421             PyObjectPlus(const PyObjectPlus& other);
00422             PyObjectPlus& operator=(const PyObjectPlus& other);
00423 #ifdef LASS_PYTHON_INHERITANCE_FROM_EMBEDDING
00424         public:
00425             PyObject* dict_;
00426 #endif
00427         private:
00428         };
00429 
00430         namespace impl
00431         {
00432             /** @internal
00433              *  Fast reentrant lock for reference count operations
00434              */
00435             inline util::CriticalSection& referenceMutex()
00436             {
00437                 using namespace util;
00438                 return *Singleton<CriticalSection, destructionPriorityInternalPythonMutex>::instance();
00439             }
00440 
00441             /** @internal
00442              *  On creation, PyObjectPlus are typeless (ob_type == 0), 
00443              *  call this function to fix that for you.  
00444              *  Objects created in C++ should call this at least once before
00445              *  being used in Python.
00446              */
00447             template <typename T> T* fixObjectType(T* iObject)
00448             {
00449                 if (meta::IsDerived<T, PyObjectPlus>::value && 
00450                     iObject && !iObject->ob_type)
00451                 {
00452                     iObject->ob_type = static_cast<PyObjectPlus*>(iObject)->_lassPyGetType();
00453                 }
00454                 return iObject;
00455             }
00456 
00457         }
00458 
00459         /** @class PyObjectStorage
00460         *  @ingroup Python
00461         *  @brief Recommended storage policy for single PyObject objects, implementation of StoragePolicy concept
00462         *  @author Tom De Muer [TDM]
00463         *  @see ObjectStorage
00464         */
00465         template <typename T, typename Cascade = meta::EmptyType>
00466         class PyObjectStorage: public Cascade
00467         {
00468         public:
00469 
00470             typedef PyObjectStorage<T, Cascade> TSelf;
00471             typedef T* TStorage;
00472             typedef T* TPointer;
00473             typedef T& TReference;
00474 
00475             TStorage& storage() { return storage_; }
00476             const TStorage& storage() const { return storage_; }
00477 
00478         protected:
00479 
00480             PyObjectStorage(): Cascade(), storage_(defaultStorage()) {}
00481             explicit PyObjectStorage(T* pointee): Cascade(), storage_(impl::fixObjectType(pointee)) {}
00482             PyObjectStorage(const PyObjectStorage& other): Cascade(other), storage_(other.storage_) {}
00483             template <typename U> PyObjectStorage(const PyObjectStorage<U, Cascade>& other): 
00484                 Cascade(other), storage_(other.storage()) {}
00485             TPointer pointer() const { return storage_; }
00486             void dispose() { storage_ = 0; }
00487             bool isNull() const { return !storage_; }
00488             void swap(TSelf& other) { Cascade::swap(other); std::swap(storage_, other.storage_);   }
00489             static TStorage defaultStorage() { return 0; }
00490         private:
00491             TStorage storage_;
00492         };
00493 
00494 
00495         /** @class PyObjectCounter
00496         *  @ingroup Python
00497         *  @brief The recommended counter for the pyobject pointers, implementation of CounterPolicy concept.
00498         *  @author Tom De Muer [TDM]
00499         *  @see DefaultCounter
00500         */
00501         class LASS_DLL PyObjectCounter
00502         {
00503         public:
00504             typedef int TCount;
00505         protected:
00506             PyObjectCounter() {}
00507             template <typename TStorage> void init(TStorage& /*pointee*/) {}
00508             template <typename TStorage> void dispose(TStorage& /*pointee*/) {}
00509             template <typename TStorage> void increment(TStorage& pointee)
00510             {
00511                 LASS_LOCK(impl::referenceMutex())
00512                 {
00513                     Py_INCREF(pointee);
00514                 }
00515             }
00516             template <typename TStorage> bool decrement(TStorage& pointee)
00517             {
00518                 bool r = false;
00519                 LASS_LOCK(impl::referenceMutex())
00520                 {
00521                     LASS_ASSERT(pointee);
00522                     r = pointee->ob_refcnt <=1;
00523                     Py_DECREF(pointee);
00524                 }
00525                 return r;
00526             }
00527             template <typename TStorage> TCount count(TStorage& pointee) const
00528             {
00529                 LASS_ASSERT(pointee);
00530                 return pointee->ob_refcnt;
00531             }
00532             void swap(PyObjectCounter& /*other*/) {}
00533         };
00534 
00535         /** templated "typedef" to a python shared pointer
00536          *  @ingroup Python
00537          */
00538         template<class T>
00539         struct PyObjectPtr
00540         {
00541             typedef util::SharedPtr<T, PyObjectStorage, PyObjectCounter> Type;
00542         };
00543 
00544         /** PyObjectPtr to a PyObject
00545          *  @ingroup Python
00546          */
00547         typedef PyObjectPtr<PyObject>::Type TPyObjPtr;
00548 
00549         namespace impl
00550         {
00551             LASS_DLL const std::string exceptionExtractMessage(
00552                     const TPyObjPtr& type, const TPyObjPtr& value);
00553         }
00554 
00555         class PythonException: public util::Exception
00556         {
00557         public:
00558             PythonException(
00559                     const TPyObjPtr& type, const TPyObjPtr& value, const TPyObjPtr& traceback, 
00560                     const std::string& loc):
00561                 util::Exception(impl::exceptionExtractMessage(type, value), loc),
00562                 type_(type),
00563                 value_(value),
00564                 traceback_(traceback)
00565             {
00566             }
00567             ~PythonException() throw() {}
00568             const python::TPyObjPtr& type() const { return type_; } 
00569             const python::TPyObjPtr& value() const { return value_; } 
00570             const python::TPyObjPtr& traceback() const { return traceback_; } 
00571         private:
00572             LASS_UTIL_EXCEPTION_PRIVATE_IMPL(PythonException)
00573             python::TPyObjPtr type_;
00574             python::TPyObjPtr value_;
00575             python::TPyObjPtr traceback_;
00576         };
00577 
00578         /** fromNakedToSharedPtrCast.
00579         *   @ingroup Python
00580         *   Helper function casting a PyObject coming from the Python interface to a SharedPtr
00581         *   object for use in C++.  Reference counts are taken care of.
00582         */
00583         template<class T>
00584         lass::util::SharedPtr<T, PyObjectStorage, PyObjectCounter>
00585         fromNakedToSharedPtrCast(PyObject* object)
00586         {
00587             LASS_LOCK(impl::referenceMutex()) 
00588             {
00589                 Py_XINCREF(object);
00590             }
00591             return util::SharedPtr<T,PyObjectStorage,PyObjectCounter>(static_cast<T*>(object));
00592         }
00593 
00594         /** fromSharedPtrToNakedCast.
00595         *   @ingroup Python
00596         *   Helper function casting an object used in C++ for use in Python.  The key operation
00597         *   done here is to take care of the reference counting. Failing to use this function may
00598         *   yield unexpected reference count.
00599         */
00600         template<class T>
00601         PyObject*
00602         fromSharedPtrToNakedCast(const util::SharedPtr<T,PyObjectStorage,PyObjectCounter>& object)
00603         {
00604             PyObject* const obj = object.get();
00605             LASS_LOCK(impl::referenceMutex()) 
00606             {
00607                 Py_XINCREF(obj);
00608             }
00609             return obj;
00610         }
00611 
00612         /** static_cast for python pointers
00613          *  @ingroup Python
00614          */  
00615         template <typename Out, typename In> inline
00616         Out staticPyCast(const In& in)
00617         {
00618             typedef typename Out::TPointer TPtr;
00619             TPtr ptr = static_cast<TPtr>(in.get());
00620             Py_XINCREF(ptr);
00621             return Out(ptr);
00622         }
00623 
00624         /** dynamic_cast for python pointers
00625          *  @ingroup Python
00626          */  
00627         template <typename Out, typename In> inline
00628         Out dynamicPyCast(const In& in)
00629         {
00630             typedef typename Out::TPointer TPtr;
00631             TPtr ptr = dynamic_cast<TPtr>(in.get());
00632             Py_XINCREF(ptr);
00633             return Out(ptr);
00634         }
00635 
00636         /** meta function to detect if a type is a PyObject-derived type
00637         *   @ingroup Python
00638         */
00639         template <typename T> struct IsPyObject: meta::IsDerived<T, PyObject> {};
00640 
00641         LASS_DLL TPyObjPtr LASS_CALL getPyObjectByName(const std::string& iName);
00642 
00643         namespace impl
00644         {
00645             LASS_DLL void LASS_CALL dealloc(PyObject* obj);
00646             LASS_DLL PyObject* LASS_CALL repr(PyObject* obj);
00647             LASS_DLL PyObject* LASS_CALL str(PyObject* obj);
00648 
00649             /** @ingroup
00650              *  @internal
00651              */
00652             class LASS_DLL OverloadLink
00653             {
00654             public:
00655                 OverloadLink();
00656                 void setNull();
00657                 void setPyCFunction(PyCFunction iOverload);
00658                 void setUnaryfunc(unaryfunc iOverload);
00659                 void setBinaryfunc(binaryfunc iOverload);
00660                 void setTernaryfunc(ternaryfunc iOverload);
00661                 
00662                 void setSsizeArgfunc(ssizeargfunc iOverload);
00663                 void setSsizeSsizeArgfunc(ssizessizeargfunc iOverload);
00664                 void setLenfunc(lenfunc iOverload);
00665                 void setSsizeObjArgProcfunc(ssizeobjargproc iOverload);
00666                 void setSsizeSsizeObjArgProcfunc(ssizessizeobjargproc iOverload);
00667                 void setObjObjProcfunc(objobjproc iOverload);
00668 
00669                 bool operator()(PyObject* iSelf, PyObject* iArgs, 
00670                     PyObject*& result) const;
00671             private:
00672                 PyCFunction pyCFunction_;
00673                 unaryfunc unaryfunc_;
00674                 binaryfunc binaryfunc_;
00675                 ternaryfunc ternaryfunc_;
00676 
00677                 ssizeargfunc ssizeargfunc_;
00678                 ssizessizeargfunc ssizessizeargfunc_;
00679                 lenfunc lenfunc_;
00680                 ssizeobjargproc ssizeobjargproc_;
00681                 ssizessizeobjargproc ssizessizeobjargproc_;
00682                 objobjproc objobjproc_;
00683             };
00684 
00685             template <PyCFunction DispatcherAddress> PyObject* unaryDispatcher(
00686                 PyObject* iSelf);
00687             template <PyCFunction DispatcherAddress> PyObject* binaryDispatcher(
00688                 PyObject* iSelf, PyObject* other);
00689             template <PyCFunction DispatcherAddress> PyObject* ternaryDispatcher(
00690                 PyObject* iSelf, PyObject* iArgs, PyObject* iKw);
00691 
00692             template <PyCFunction DispatcherAddress> PyObject* ssizeargDispatcher(
00693                 PyObject *, Py_ssize_t);
00694             template <PyCFunction DispatcherAddress> PyObject* ssizessizeargDispatcher(
00695                 PyObject *, Py_ssize_t, Py_ssize_t);
00696             template <PyCFunction DispatcherAddress> Py_ssize_t lenDispatcher(
00697                 PyObject *);
00698             template <PyCFunction DispatcherAddress> int ssizeobjargDispatcher(
00699                 PyObject *, Py_ssize_t, PyObject *);
00700             template <PyCFunction DispatcherAddress> int ssizessizeobjargDispatcher(
00701                 PyObject *, Py_ssize_t, Py_ssize_t, PyObject *);
00702             template <PyCFunction DispatcherAddress> int objobjDispatcher(
00703                 PyObject *, PyObject *);
00704 
00705 
00706             /** @ingroup
00707              *  @internal
00708              */
00709             template <PyCFunction DispatcherAddress>
00710             struct DispatcherConvertor
00711             {
00712                 static PyObject* asTernary(
00713                         PyObject* iSelf, PyObject* iArgs, PyObject* iKw)
00714                 {
00715                     if (iKw)
00716                     {
00717                         PyErr_SetString(PyExc_TypeError, 
00718                             "keyword arguments are not supported");
00719                         return 0;
00720                     }
00721                     return DispatcherAddress(iSelf, iArgs);
00722                 }
00723             };
00724 
00725             /** @ingroup
00726              *  @internal
00727              */
00728             struct LASS_DLL CompareFunc
00729             {
00730                 PyCFunction dispatcher;
00731                 int op;
00732                 CompareFunc(PyCFunction dispatcher, int op): dispatcher(dispatcher), op(op) {}
00733             };
00734 
00735             /** @ingroup
00736              *  @internal
00737              */
00738             typedef std::vector<CompareFunc> TCompareFuncs;
00739 
00740             /** @ingroup
00741              *  @internal
00742              */
00743             template <typename CppClass>
00744             struct RichCompare
00745             {
00746                 static PyObject* call(PyObject* self, PyObject* other, int op)
00747                 {
00748                     if (other==Py_None)
00749                     {
00750                         // we need to treat the None type differently because the pyGet/BuildSimpleObject are able to cast
00751                         // from None but if you give that thing to a reference, then you are in big trouble
00752                         switch (op)
00753                         {
00754                         case Py_EQ:
00755                             {
00756                                 if (self==other)
00757                                     Py_RETURN_TRUE;
00758                                 else
00759                                     Py_RETURN_FALSE;
00760                             }
00761                         case Py_NE:
00762                             {
00763                                 if (self!=other)
00764                                     Py_RETURN_TRUE;
00765                                 else
00766                                     Py_RETURN_FALSE;
00767                             }
00768                         // don't define any order relation on None
00769                         default:
00770                             Py_RETURN_FALSE;
00771                         };
00772                     }
00773 
00774                     TPyObjPtr args(Py_BuildValue("(O)", other));
00775                     const TCompareFuncs::const_iterator end = CppClass::_lassPyCompareFuncs.end();
00776                     for (TCompareFuncs::const_iterator i = CppClass::_lassPyCompareFuncs.begin(); i != end; ++i)
00777                     {
00778                         if (i->op == op)
00779                         {
00780                             PyObject* result = (i->dispatcher)(self, args.get());\
00781                             if (result || PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError))
00782                             {
00783                                 return result;
00784                             }
00785                         }
00786                     }
00787 
00788                     return RichCompare<typename CppClass::_lassPyParentType>::call(self, other, op);
00789                 }
00790             };
00791 
00792             /** @ingroup
00793              *  @internal
00794              */
00795             template <>
00796             struct RichCompare<PyObjectPlus>
00797             {
00798                 static PyObject* call(PyObject* /*self*/, PyObject* /*other*/, int op)
00799                 {
00800                     static char* symbols[] = { "<", "<=", "==", "!=", ">", ">=" };
00801                     LASS_ASSERT(op >= 0 && op <= Py_GE);
00802                     std::ostringstream buffer;
00803                     buffer << "Comparison operator " << symbols[op] << " not implemented for this type";
00804                     PyErr_SetString(PyExc_NotImplementedError, buffer.str().c_str());
00805                     return 0;               
00806                 }
00807             };
00808 
00809             class StaticMemberHelper
00810             {
00811             public:
00812                 virtual ~StaticMemberHelper() {}
00813                 virtual PyObject* build() const = 0;
00814             };
00815             typedef util::SharedPtr<StaticMemberHelper> TStaticMemberHelperPtr;
00816             template <typename T>
00817             class StaticMemberHelperObject: public StaticMemberHelper
00818             {
00819             public:
00820                 StaticMemberHelperObject(const T& obj): obj_(obj) {}
00821                 PyObject* build() const { return pyBuildSimpleObject(obj_); }
00822             private:
00823                 T obj_;
00824             };
00825             template <>
00826             class StaticMemberHelperObject<PyObject*>: public StaticMemberHelper
00827             {
00828             public:
00829                 StaticMemberHelperObject(PyObject* obj): obj_(obj) {}
00830                 PyObject* build() const { return obj_; }
00831             private:
00832                 PyObject* obj_;
00833             };
00834             template <typename T>
00835             inline TStaticMemberHelperPtr staticMemberHelperObject(const T& obj)
00836             {
00837                 return TStaticMemberHelperPtr(new StaticMemberHelperObject<T>(obj));
00838             }
00839             class StaticMemberHelperType: public StaticMemberHelper
00840             {
00841             public:
00842                 StaticMemberHelperType(PyTypeObject* type): type_(type) {}
00843                 PyObject* build() const { return reinterpret_cast<PyObject*>(type_); }
00844             private:
00845                 PyTypeObject* type_;
00846             };
00847             inline TStaticMemberHelperPtr staticMemberHelperType(PyTypeObject* type)
00848             {
00849                 return TStaticMemberHelperPtr(new StaticMemberHelperType(type));
00850             }
00851 
00852             /** @ingroup
00853              *  @internal
00854              */
00855             struct StaticMember
00856             {
00857                 TStaticMemberHelperPtr member;
00858                 PyTypeObject* parentType;
00859                 std::vector<PyMethodDef>* methods;
00860                 std::vector<PyGetSetDef>* getSetters;
00861                 const std::vector<StaticMember>* statics;
00862                 const char* name;
00863                 const char* doc;
00864             };
00865             typedef std::vector<StaticMember> TStaticMembers;
00866 
00867             /** @ingroup
00868              *  @internal
00869              *  predicate to find a StaticMember by name.
00870              */
00871             class LASS_DLL StaticMemberEqual
00872             {
00873             public:
00874                 StaticMemberEqual(const char* iName);
00875                 bool operator()(const StaticMember& iMethod) const;
00876             private:
00877                 const char* name_;
00878             };
00879 
00880             /** @ingroup
00881              *  @internal
00882              *  predicate to check of a python method has the correct name.
00883              */
00884             class LASS_DLL PyMethodEqual
00885             {
00886             public:
00887                 PyMethodEqual( const char* iName );
00888                 bool operator()(const PyMethodDef& iMethod) const;
00889             private:
00890                 const char* name_;
00891             };
00892 
00893             LASS_DLL StaticMember LASS_CALL createStaticMember(
00894                 const char* iName, const char * iDocumentation, const TStaticMemberHelperPtr& iObject, 
00895                 PyTypeObject* iParentType = 0, std::vector<PyMethodDef>* iMethods = 0, 
00896                 std::vector<PyGetSetDef>* iGetSetters = 0, 
00897                 const TStaticMembers* iStatics = 0);
00898             LASS_DLL PyMethodDef LASS_CALL createPyMethodDef(
00899                 const char *ml_name, PyCFunction ml_meth, int ml_flags, 
00900                 const char *ml_doc);
00901             LASS_DLL PyGetSetDef LASS_CALL createPyGetSetDef(
00902                 const char* name, getter get, setter set, const char* doc, void* closure);
00903 
00904             LASS_DLL void LASS_CALL injectStaticMembers(
00905                 PyTypeObject& iPyType, const TStaticMembers& iStatics);
00906             LASS_DLL void LASS_CALL finalizePyType(
00907                 PyTypeObject& iPyType, PyTypeObject& iPyParentType, 
00908                 std::vector<PyMethodDef>& iMethods, 
00909                 std::vector<PyGetSetDef>& iGetSetters, 
00910                 const TStaticMembers& iStatics, 
00911                 const char* iModuleName, const char* iDocumentation);
00912             LASS_DLL void LASS_CALL addModuleFunction(
00913                 std::vector<PyMethodDef>& ioModuleMethods, 
00914                 const char* iMethodName, const char* iDocumentation,
00915                 PyCFunction iMethodDispatcher, PyCFunction& oOverloadChain);
00916             LASS_DLL void LASS_CALL addClassMethod(
00917                 PyTypeObject& pyType, 
00918                 std::vector<PyMethodDef>& classMethods, TCompareFuncs& compareFuncs,
00919                 const char* methodName, const char* documentation,
00920                 PyCFunction dispatcher, unaryfunc dispatcherUnary, 
00921                 binaryfunc dispatcherBinary, ternaryfunc dispatcherTernary, 
00922                 ssizeargfunc dispatcherSsizeArg, ssizessizeargfunc dispatcherSsizeSsizeArg,
00923                 lenfunc dispatcherLen, ssizeobjargproc dispatcherSsizeObjArgProc,
00924                 ssizessizeobjargproc dispatcherSsizeSsizeObjArgProc, 
00925                 objobjproc dispatcherObjObjProc,
00926                 OverloadLink& overloadChain);
00927 
00928             template <typename CppClass> void injectClassInModule(
00929                 PyObject* iModule, const char* iClassDocumentation);
00930             template <typename CppClass> void addClassStaticMethod(
00931                 const char* iMethodName, const char* iDocumentation,
00932                 PyCFunction iMethodDispatcher, PyCFunction& oOverloadChain);
00933             template <typename CppClass, typename T> void addClassStaticConst(
00934                 const char* iName, const T& iValue);
00935             template <typename InnerCppClass> void addClassInnerClass(
00936                 TStaticMembers& oOuterStatics,
00937                 const char* iInnerClassName, const char* iDocumentation);
00938 
00939             template <typename In, typename Out> int pyNumericCast(In iIn, Out& oV);
00940             template <typename Integer> int pyGetSignedObject(
00941                 PyObject* iValue, Integer& oV);
00942             template <typename Integer> int pyGetUnsignedObject(
00943                 PyObject* iValue, Integer& oV);
00944             template <typename Float> int pyGetFloatObject(
00945                 PyObject* iValue, Float& oV);
00946 
00947             LASS_DLL void LASS_CALL addMessageHeader(const std::string& iHeader);
00948             LASS_DLL bool LASS_CALL checkSequenceSize(PyObject* iValue, Py_ssize_t iExpectedSize);
00949             LASS_DLL TPyObjPtr LASS_CALL checkedFastSequence(PyObject* iValue, Py_ssize_t iExpectedSize);
00950         }
00951     }
00952 }
00953 
00954 #if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC
00955 #   pragma warning(pop)
00956 #endif
00957 
00958 #include "pyobject_plus.inl"
00959 
00960 #endif

Generated on Mon Nov 10 14:21:06 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo