| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- /*
- * This source file is part of libRocket, the HTML/CSS Interface Middleware
- *
- * For the latest information, see http://www.librocket.com
- *
- * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
- #if !defined(BOOST_PP_IS_ITERATING)
- # error PyWrapperIter - do not include this file!
- #endif
- #define N BOOST_PP_ITERATION()
- /**
- Generic Python Wrapper, using Boost Preprocessor Iteration to Generate Variants
-
- Relies on a Rocket::Core::ReferenceCountable base class for reference counting.
-
- Traps ReferenceActivated/Deactivated calls and makes them behave like
- they should for python based objects.
-
- @author Lloyd Weehuizen
- */
- #define WRAPPER_PARAM(x, n, d) , d
- template < typename T BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS_Z(1, N, typename A) >
- 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
- {
- public:
- 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))
- {
- // Set self to NULL, so we can trap the reference deactivated and not pass it down
- this->self = NULL;
- // We have to remove the C++ reference count that all C++ objects start with here,
- // otherwise if an object is created in python and destroyed by python, the C++ ref count will
- // remain 1. The PyWrapperInstancer will increase the refcount again, to ensure a correct refcount
- // if the object was created by C++
- T::RemoveReference();
- // If the C++ reference count is not 0 at this point, it means additional references have been added
- // during the classes constructor. We have to propogate these references into python.
- for (int i = 0; i < this->T::GetReferenceCount(); i++)
- Py_INCREF(self);
- // Store self
- this->self = self;
- }
- Wrapper(PyObject* self, const T& other) : T(other)
- {
- this->self = self;
- }
- virtual ~Wrapper()
- {
- // We should only be deleted when python says the refcnt is 0, if we
- // are being deleted prematurely, something is wrong!
- ROCKET_ASSERTMSG(self->ob_refcnt == 0, "Python object being cleared up prematurely, reference count not 0.");
- ROCKET_ASSERT(this->T::GetReferenceCount() == 0);
- }
- /// Override AddReference so we can push the call through to python
- virtual void AddReference()
- {
- Py_INCREF(self);
-
- T::AddReference();
- }
- /// Overrride RemoveReference so we can push the call through to python
- virtual void RemoveReference()
- {
- T::RemoveReference();
- Py_DECREF(self);
- }
-
- virtual int GetReferenceCount()
- {
- // C++ reference counts are always reflected in the python ref count
- return self->ob_refcnt;
- }
- virtual void OnReferenceDeactivate()
- {
- // If self is NULL, don't pass the call down, as this is the initial
- // T::RemoveReference from the constructor
- if (self)
- T::OnReferenceDeactivate();
- }
- // Script object access
- virtual void* GetScriptObject() const { return self; }
- protected:
- PyObject* self;
- };
- #undef WRAPPER_PARAM
|