summaryrefslogtreecommitdiffstats
path: root/lib/kross/api/proxy.h
blob: f25a4845afc7aff72f6c5f8023a847808e0678d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
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