/*************************************************************************** * proxy.h * This file is part of the KDE project * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * You should have received a copy of the GNU Library General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. ***************************************************************************/ #ifndef KROSS_API_PROXY_H #define KROSS_API_PROXY_H #include "../main/krossconfig.h" #include "object.h" #include "variant.h" #include "list.h" #include namespace Kross { namespace Api { /** * \internal used struct to translate an argument-value dynamicly. */ template struct ProxyArgTranslator { OBJ* m_object; ProxyArgTranslator(Kross::Api::Object* obj) { m_object = Kross::Api::Object::fromObject(obj); } template inline operator T () { return m_object->operator T(); } }; /** * \internal used struct to translate a return-value dynamicly. */ struct ProxyRetTranslator { template inline static Object::Ptr cast(TYPE t) { return RETURNOBJ::toObject(t); } }; /** * The ProxyFunction template-class is used to publish any C/C++ * method (not only slots) of a struct or class instance as a * a \a Function to Kross. * * With this class we don't need to have a method-wrapper for * each single function what a) should reduce the code needed for * wrappers and b) is more typesafe cause the connection to the * C/C++ method is done on compiletime. * * Example how a ProxyFunction may got used; * @code * #include "../api/class.h" * #include "../api/proxy.h" * // The class which should be published. * class MyClass : public Kross::Api::Class { * public: * MyClass(const TQString& name) : Kross::Api::Class(name) { * // publish the function myfunc, so that scripting-code is able * // to call that method. * this->addProxyFunction < * Kross::Api::Variant, // the uint returnvalue is handled with Variant. * Kross::Api::Variant, // the TQString argument is handled with Variant too. * MyClass // the MyClass* is handled implicit by our class. * > ( "myfuncname", // the name the function should be published as. * this, // pointer to the class-instance which has the method. * &TestPluginObject::myfunc ); // pointer to the method itself. * } * virtual ~MyClass() {} * virtual const TQString getClassName() const { return "MyClass"; } * private: * uint myfunc(const TQCString&, MyClass* myotherclass) { * // This method will be published to the scripting backend. So, scripting * // code is able to call this method. * } * } * @endcode */ template< class INSTANCE, // the objectinstance typename METHOD, // the method-signature class RETURNOBJ,// = Kross::Api::Object, // return-value class ARG1OBJ = Kross::Api::Object, // first parameter-value class ARG2OBJ = Kross::Api::Object, // second parameter-value class ARG3OBJ = Kross::Api::Object, // theird parameter-value class ARG4OBJ = Kross::Api::Object // forth parameter-value > class ProxyFunction : public Function { template friend struct ProxyFunctionCaller; private: /// Pointer to the objectinstance which method should be called. INSTANCE* m_instance; /// Pointer to the method which should be called. const METHOD m_method; /// First default argument. TDESharedPtr m_defarg1; /// Second default argument. TDESharedPtr m_defarg2; /// Theird default argument. TDESharedPtr m_defarg3; /// Forth default argument. TDESharedPtr m_defarg4; /** * \internal used struct that does the execution of the wrapped * method. */ template struct ProxyFunctionCaller { inline static Object::Ptr exec(PROXYFUNC* self, Kross::Api::Object* arg1, Kross::Api::Object* arg2, Kross::Api::Object* arg3, Kross::Api::Object* arg4) { return ProxyRetTranslator::cast( ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator(arg1), ProxyArgTranslator(arg2), ProxyArgTranslator(arg3), ProxyArgTranslator(arg4) ) ); } }; /** * \internal template-specialization of the \a ProxyFunctionCaller * above which handles void-returnvalues. We need to handle this * special case seperatly cause compilers deny to return void :-/ */ template struct ProxyFunctionCaller { inline static Object::Ptr exec(PROXYFUNC* self, Kross::Api::Object* arg1, Kross::Api::Object* arg2, Kross::Api::Object* arg3, Kross::Api::Object* arg4) { ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator(arg1), ProxyArgTranslator(arg2), ProxyArgTranslator(arg3), ProxyArgTranslator(arg4) ); return 0; // void return-value } }; public: /** * Constructor. * * \param instance The objectinstance to which the \p method * belongs to. * \param method The method-pointer. */ ProxyFunction(INSTANCE* instance, const METHOD& method, ARG1OBJ* defarg1 = 0, ARG2OBJ* defarg2 = 0, ARG3OBJ* defarg3 = 0, ARG4OBJ* defarg4 = 0) : m_instance(instance), m_method(method), m_defarg1(defarg1), m_defarg2(defarg2), m_defarg3(defarg3), m_defarg4(defarg4) {} /** * This method got called if the wrapped method should be executed. * * \param args The optional list of arguments passed to the * execution-call. * \return The returnvalue of the functioncall. It will be NULL if * the functioncall doesn't provide us a returnvalue (e.g. * if the function has void as returnvalue). */ Object::Ptr call(List::Ptr args) { return ProxyFunctionCaller::exec(this, args->item(0, m_defarg1), args->item(1, m_defarg2), args->item(2, m_defarg3), args->item(3, m_defarg4) ); } }; /** * Template-specialization of the \a ProxyFunction above with three arguments. */ template class ProxyFunction : public Function { template friend struct ProxyFunctionCaller; private: INSTANCE* m_instance; const METHOD m_method; TDESharedPtr m_defarg1; TDESharedPtr m_defarg2; TDESharedPtr m_defarg3; template struct ProxyFunctionCaller { inline static Object::Ptr exec(PROXYFUNC* self, Kross::Api::Object* arg1, Kross::Api::Object* arg2, Kross::Api::Object* arg3) { return ProxyRetTranslator::cast( ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator(arg1), ProxyArgTranslator(arg2), ProxyArgTranslator(arg3) ) ); } }; template struct ProxyFunctionCaller { inline static Object::Ptr exec(PROXYFUNC* self, Kross::Api::Object* arg1, Kross::Api::Object* arg2, Kross::Api::Object* arg3) { ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator(arg1), ProxyArgTranslator(arg2), ProxyArgTranslator(arg3) ); return 0; } }; public: ProxyFunction(INSTANCE* instance, const METHOD& method, ARG1OBJ* defarg1 = 0, ARG2OBJ* defarg2 = 0, ARG3OBJ* defarg3 = 0) : m_instance(instance), m_method(method), m_defarg1(defarg1), m_defarg2(defarg2), m_defarg3(defarg3) {} Object::Ptr call(List::Ptr args) { return ProxyFunctionCaller::exec(this, args->item(0, m_defarg1), args->item(1, m_defarg2), args->item(2, m_defarg3) ); } }; /** * Template-specialization of the \a ProxyFunction above with two arguments. */ template class ProxyFunction : public Function { template friend struct ProxyFunctionCaller; private: INSTANCE* m_instance; const METHOD m_method; TDESharedPtr m_defarg1; TDESharedPtr m_defarg2; template struct ProxyFunctionCaller { inline static Object::Ptr exec(PROXYFUNC* self, Kross::Api::Object* arg1, Kross::Api::Object* arg2) { return ProxyRetTranslator::cast( ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator(arg1), ProxyArgTranslator(arg2) ) ); } }; template struct ProxyFunctionCaller { inline static Object::Ptr exec(PROXYFUNC* self, Kross::Api::Object* arg1, Kross::Api::Object* arg2) { ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator(arg1), ProxyArgTranslator(arg2) ); return 0; } }; public: ProxyFunction(INSTANCE* instance, const METHOD& method, ARG1OBJ* defarg1 = 0, ARG2OBJ* defarg2 = 0) : m_instance(instance), m_method(method), m_defarg1(defarg1), m_defarg2(defarg2) {} Object::Ptr call(List::Ptr args) { return ProxyFunctionCaller::exec(this, args->item(0, m_defarg1), args->item(1, m_defarg2) ); } }; /** * Template-specialization of the \a ProxyFunction above with one argument. */ template class ProxyFunction : public Function { template friend struct ProxyFunctionCaller; private: INSTANCE* m_instance; const METHOD m_method; TDESharedPtr m_defarg1; template struct ProxyFunctionCaller { inline static Object::Ptr exec(PROXYFUNC* self, Kross::Api::Object* arg1) { return ProxyRetTranslator::cast( ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator(arg1) ) ); } }; template struct ProxyFunctionCaller { inline static Object::Ptr exec(PROXYFUNC* self, Kross::Api::Object* arg1) { ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator(arg1) ); return 0; } }; public: ProxyFunction(INSTANCE* instance, const METHOD& method, ARG1OBJ* defarg1 = 0) : m_instance(instance), m_method(method), m_defarg1(defarg1) {} Object::Ptr call(List::Ptr args) { return ProxyFunctionCaller::exec(this, args->item(0, m_defarg1) ); } }; /** * Template-specialization of the \a ProxyFunction above with no arguments. */ template class ProxyFunction : public Function { template friend struct ProxyFunctionCaller; private: INSTANCE* m_instance; const METHOD m_method; template struct ProxyFunctionCaller { inline static Object::Ptr exec(PROXYFUNC* self) { return ProxyRetTranslator::cast( ( (self->m_instance)->*(self->m_method) )() ); } }; template struct ProxyFunctionCaller { inline static Object::Ptr exec(PROXYFUNC* self) { ( (self->m_instance)->*(self->m_method) )(); return 0; } }; public: ProxyFunction(INSTANCE* instance, const METHOD& method) : m_instance(instance), m_method(method) {} Object::Ptr call(List::Ptr) { return ProxyFunctionCaller::exec(this); } }; }} #endif