diff options
Diffstat (limited to 'lib/kross/api/proxy.h')
-rw-r--r-- | lib/kross/api/proxy.h | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/lib/kross/api/proxy.h b/lib/kross/api/proxy.h new file mode 100644 index 00000000..f25a4845 --- /dev/null +++ b/lib/kross/api/proxy.h @@ -0,0 +1,342 @@ +/*************************************************************************** + * 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 <qstring.h> + +namespace Kross { namespace Api { + + /** + * \internal used struct to translate an argument-value dynamicly. + */ + template<class OBJ> + struct ProxyArgTranslator { + OBJ* m_object; + ProxyArgTranslator(Kross::Api::Object* obj) { + m_object = Kross::Api::Object::fromObject<OBJ>(obj); + } + template<typename T> + inline operator T () { + return m_object->operator T(); + } + }; + + /** + * \internal used struct to translate a return-value dynamicly. + */ + struct ProxyRetTranslator { + template<class RETURNOBJ, typename TYPE> + 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<MyClass> { + * public: + * MyClass(const QString& name) : Kross::Api::Class<MyClass>(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 QString 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 QString getClassName() const { return "MyClass"; } + * private: + * uint myfunc(const QCString&, 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<class PROXYFUNC, typename RETURNTYPE> + 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. + KSharedPtr<ARG1OBJ> m_defarg1; + /// Second default argument. + KSharedPtr<ARG2OBJ> m_defarg2; + /// Theird default argument. + KSharedPtr<ARG3OBJ> m_defarg3; + /// Forth default argument. + KSharedPtr<ARG4OBJ> m_defarg4; + + /** + * \internal used struct that does the execution of the wrapped + * method. + */ + template<class PROXYFUNC, typename RETURNTYPE> + 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<RETURNTYPE>( + ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator<ARG1OBJ>(arg1), ProxyArgTranslator<ARG2OBJ>(arg2), ProxyArgTranslator<ARG3OBJ>(arg3), ProxyArgTranslator<ARG4OBJ>(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<class PROXYFUNC> + struct ProxyFunctionCaller<PROXYFUNC, void> { + 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<ARG1OBJ>(arg1), ProxyArgTranslator<ARG1OBJ>(arg2), ProxyArgTranslator<ARG3OBJ>(arg3), ProxyArgTranslator<ARG4OBJ>(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<ProxyFunction, RETURNOBJ>::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 INSTANCE, typename METHOD, class RETURNOBJ, class ARG1OBJ, class ARG2OBJ, class ARG3OBJ> + class ProxyFunction<INSTANCE, METHOD, RETURNOBJ, ARG1OBJ, ARG2OBJ, ARG3OBJ> : public Function + { + template<class PROXYFUNC, typename RETURNTYPE> + friend struct ProxyFunctionCaller; + private: + INSTANCE* m_instance; + const METHOD m_method; + KSharedPtr<ARG1OBJ> m_defarg1; + KSharedPtr<ARG2OBJ> m_defarg2; + KSharedPtr<ARG3OBJ> m_defarg3; + + template<class PROXYFUNC, typename RETURNTYPE> + struct ProxyFunctionCaller { + inline static Object::Ptr exec(PROXYFUNC* self, Kross::Api::Object* arg1, Kross::Api::Object* arg2, Kross::Api::Object* arg3) { + return ProxyRetTranslator::cast<RETURNTYPE>( + ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator<ARG1OBJ>(arg1), ProxyArgTranslator<ARG2OBJ>(arg2), ProxyArgTranslator<ARG3OBJ>(arg3) ) + ); + } + }; + + template<class PROXYFUNC> + struct ProxyFunctionCaller<PROXYFUNC, void> { + 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<ARG1OBJ>(arg1), ProxyArgTranslator<ARG2OBJ>(arg2), ProxyArgTranslator<ARG3OBJ>(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<ProxyFunction, RETURNOBJ>::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 INSTANCE, typename METHOD, class RETURNOBJ, class ARG1OBJ, class ARG2OBJ> + class ProxyFunction<INSTANCE, METHOD, RETURNOBJ, ARG1OBJ, ARG2OBJ> : public Function + { + template<class PROXYFUNC, typename RETURNTYPE> + friend struct ProxyFunctionCaller; + private: + INSTANCE* m_instance; + const METHOD m_method; + KSharedPtr<ARG1OBJ> m_defarg1; + KSharedPtr<ARG2OBJ> m_defarg2; + + template<class PROXYFUNC, typename RETURNTYPE> + struct ProxyFunctionCaller { + inline static Object::Ptr exec(PROXYFUNC* self, Kross::Api::Object* arg1, Kross::Api::Object* arg2) { + return ProxyRetTranslator::cast<RETURNTYPE>( + ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator<ARG1OBJ>(arg1), ProxyArgTranslator<ARG2OBJ>(arg2) ) + ); + } + }; + + template<class PROXYFUNC> + struct ProxyFunctionCaller<PROXYFUNC, void> { + inline static Object::Ptr exec(PROXYFUNC* self, Kross::Api::Object* arg1, Kross::Api::Object* arg2) { + ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator<ARG1OBJ>(arg1), ProxyArgTranslator<ARG2OBJ>(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<ProxyFunction, RETURNOBJ>::exec(this, + args->item(0, m_defarg1), args->item(1, m_defarg2) + ); + } + }; + + /** + * Template-specialization of the \a ProxyFunction above with one argument. + */ + template<class INSTANCE, typename METHOD, class RETURNOBJ, class ARG1OBJ> + class ProxyFunction<INSTANCE, METHOD, RETURNOBJ, ARG1OBJ> : public Function + { + template<class PROXYFUNC, typename RETURNTYPE> + friend struct ProxyFunctionCaller; + private: + INSTANCE* m_instance; + const METHOD m_method; + KSharedPtr<ARG1OBJ> m_defarg1; + + template<class PROXYFUNC, typename RETURNTYPE> + struct ProxyFunctionCaller { + inline static Object::Ptr exec(PROXYFUNC* self, Kross::Api::Object* arg1) { + return ProxyRetTranslator::cast<RETURNTYPE>( + ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator<ARG1OBJ>(arg1) ) + ); + } + }; + + template<class PROXYFUNC> + struct ProxyFunctionCaller<PROXYFUNC, void> { + inline static Object::Ptr exec(PROXYFUNC* self, Kross::Api::Object* arg1) { + ( (self->m_instance)->*(self->m_method) )( ProxyArgTranslator<ARG1OBJ>(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<ProxyFunction, RETURNOBJ>::exec(this, + args->item(0, m_defarg1) + ); + } + }; + + /** + * Template-specialization of the \a ProxyFunction above with no arguments. + */ + template<class INSTANCE, typename METHOD, class RETURNOBJ> + class ProxyFunction<INSTANCE, METHOD, RETURNOBJ> : public Function + { + template<class PROXYFUNC, typename RETURNTYPE> + friend struct ProxyFunctionCaller; + private: + INSTANCE* m_instance; + const METHOD m_method; + + template<class PROXYFUNC, typename RETURNTYPE> + struct ProxyFunctionCaller { + inline static Object::Ptr exec(PROXYFUNC* self) { + return ProxyRetTranslator::cast<RETURNTYPE>( + ( (self->m_instance)->*(self->m_method) )() + ); + } + }; + + template<class PROXYFUNC> + struct ProxyFunctionCaller<PROXYFUNC, void> { + 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<ProxyFunction, RETURNOBJ>::exec(this); + } + }; + +}} + +#endif + |