WrapperIter.h

00001 /*
00002  * This source file is part of libRocket, the HTML/CSS Interface Middleware
00003  *
00004  * For the latest information, see http://www.librocket.com
00005  *
00006  * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
00007  *
00008  * Permission is hereby granted, free of charge, to any person obtaining a copy
00009  * of this software and associated documentation files (the "Software"), to deal
00010  * in the Software without restriction, including without limitation the rights
00011  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00012  * copies of the Software, and to permit persons to whom the Software is
00013  * furnished to do so, subject to the following conditions:
00014  *
00015  * The above copyright notice and this permission notice shall be included in
00016  * all copies or substantial portions of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00019  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00020  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00021  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00022  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00023  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00024  * THE SOFTWARE.
00025  *
00026  */
00027 
00028 #if !defined(BOOST_PP_IS_ITERATING)
00029 #  error PyWrapperIter - do not include this file!
00030 #endif
00031 
00032 #define N BOOST_PP_ITERATION()
00033 
00045 #define WRAPPER_PARAM(x, n, d) , d
00046 
00047 template < typename T BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS_Z(1, N, typename A) >
00048 class Wrapper< T BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS_Z(1, N, A) BOOST_PP_REPEAT_1( BOOST_PP_SUB(BOOST_PP_INC(WRAPPER_MAX_ARGS), N), WRAPPER_PARAM, WrapperNone) > : public T
00049 {
00050 public: 
00051         Wrapper(PyObject* self BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, a)) : T(BOOST_PP_ENUM_PARAMS_Z(1, N, a))
00052         {
00053                 // Set self to NULL, so we can trap the reference deactivated and not pass it down
00054                 this->self = NULL;
00055 
00056                 // We have to remove the C++ reference count that all C++ objects start with here,
00057                 // otherwise if an object is created in python and destroyed by python, the C++ ref count will
00058                 // remain 1. The PyWrapperInstancer will increase the refcount again, to ensure a correct refcount
00059                 // if the object was created by C++
00060                 T::RemoveReference();
00061 
00062                 // If the C++ reference count is not 0 at this point, it means additional references have been added
00063                 // during the classes constructor. We have to propogate these references into python.
00064                 for (int i = 0; i < this->T::GetReferenceCount(); i++)
00065                         Py_INCREF(self);
00066 
00067                 // Store self
00068                 this->self = self;
00069         }
00070 
00071         Wrapper(PyObject* self, const T& other) : T(other)
00072         {
00073                 this->self = self;              
00074         }
00075 
00076         virtual ~Wrapper()
00077         {               
00078                 // We should only be deleted when python says the refcnt is 0, if we
00079                 // are being deleted prematurely, something is wrong!
00080                 ROCKET_ASSERTMSG(self->ob_refcnt == 0, "Python object being cleared up prematurely, reference count not 0.");
00081                 ROCKET_ASSERT(this->T::GetReferenceCount() == 0);
00082         }
00083 
00085         virtual void AddReference()
00086         {
00087                 Py_INCREF(self);
00088                 
00089                 T::AddReference();
00090         }
00091 
00093         virtual void RemoveReference()
00094         {
00095                 T::RemoveReference();
00096 
00097                 Py_DECREF(self);
00098         }
00099         
00100         virtual int GetReferenceCount()
00101         {
00102                 // C++ reference counts are always reflected in the python ref count
00103                 return self->ob_refcnt;
00104         }
00105 
00106         virtual void OnReferenceDeactivate()
00107         {
00108                 // If self is NULL, don't pass the call down, as this is the initial 
00109                 // T::RemoveReference from the constructor
00110                 if (self)
00111                         T::OnReferenceDeactivate();
00112         }
00113 
00114         // Script object access
00115         virtual void* GetScriptObject() const { return self; }
00116 
00117 protected:
00118         PyObject* self;
00119 };
00120 
00121 #undef WRAPPER_PARAM
00122