Line data Source code
1 : /*
2 : * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Andreas Vogel
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 :
34 : #ifndef __H__UG_BRIDGE__CLASS__
35 : #define __H__UG_BRIDGE__CLASS__
36 :
37 : #include <cstdlib>
38 : #include <cstring>
39 : #include <string>
40 : #include <boost/type_traits.hpp>
41 : #include <boost/optional.hpp>
42 :
43 : #include "parameter_stack.h"
44 : #include "function_traits.h"
45 : #include "global_function.h"
46 : #include "common/common.h"
47 : #include "error.h"
48 : #include "registry_util.h"
49 :
50 : #ifdef PROFILE_BRIDGE
51 : #ifndef UG_PROFILER
52 : #error "You need to define UG_PROFILER to use PROFILE_BRIDGE"
53 : #endif
54 : #include "common/profiler/runtime_profile_info.h"
55 : #else
56 : #endif
57 :
58 :
59 : namespace ug
60 : {
61 : namespace bridge
62 : {
63 :
64 : /// \addtogroup registry
65 : /// \{
66 :
67 : class MethodPtrWrapper
68 : {
69 : public:
70 : template <typename TMethod>
71 4198 : MethodPtrWrapper(TMethod m)
72 : {
73 4198 : size = sizeof(TMethod);
74 4198 : data = malloc(size);
75 : memcpy(data, &m, size);
76 4198 : }
77 :
78 4198 : MethodPtrWrapper(const MethodPtrWrapper& mpw)
79 4198 : {
80 4198 : size = mpw.size;
81 4198 : data = malloc(size);
82 : memcpy(data, mpw.get_raw_ptr(), size);
83 4198 : }
84 :
85 0 : ~MethodPtrWrapper() {free(data);}
86 :
87 4198 : void* get_raw_ptr() const {return data;}
88 :
89 : protected:
90 : void* data;
91 : int size;
92 : };
93 :
94 : /// Performs a reinterpret cast on the given pointer, then calls delete on it
95 0 : template <class TClass> void CastAndDelete(const void* ptr)
96 : {
97 0 : delete reinterpret_cast<const TClass*>(ptr);
98 0 : }
99 :
100 0 : template <> inline void CastAndDelete<void>(const void* ptr)
101 : {
102 0 : UG_THROW("Can't delete instance of class 'void'");
103 : }
104 :
105 :
106 : /** function exported from ug
107 : * This class describes a wrapper for a c++ - function, that is exported by ug
108 : */
109 : class ExportedMethod : public ExportedFunctionBase
110 : {
111 : public:
112 : // all c++ functions are wrapped by a proxy function of the following type
113 : typedef void (*ProxyFunc)(const MethodPtrWrapper& func, void* obj,
114 : const ParameterStack& in, ParameterStack& out);
115 :
116 : public:
117 4198 : ExportedMethod( const MethodPtrWrapper& m, ProxyFunc pf,
118 : const std::string& name, const std::string& className,
119 : const std::string& methodOptions,
120 : const std::string& retValInfos, const std::string& paramInfos,
121 : const std::string& tooltip, const std::string& help)
122 4198 : : ExportedFunctionBase(name, methodOptions, retValInfos, paramInfos, tooltip, help),
123 4198 : m_ptrWrapper(m), m_proxy_func(pf), m_className(className)
124 : #ifdef PROFILE_BRIDGE
125 : ,m_dpi((m_className + ":" + name).c_str(), true, "registry", false)
126 : #endif
127 : {
128 4198 : }
129 :
130 : /// executes the function
131 : void execute(void* obj, const ParameterStack& paramsIn, ParameterStack& paramsOut) const
132 : {
133 : #ifdef PROFILE_BRIDGE
134 : m_dpi.beginNode();
135 : #endif
136 0 : m_proxy_func(m_ptrWrapper, obj, paramsIn, paramsOut);
137 :
138 : #ifdef PROFILE_BRIDGE
139 : m_dpi.endNode();
140 : #endif
141 0 : }
142 :
143 : /// \todo: replace this method with a better integrated way.
144 : template <typename TFunc>
145 : void create_parameter_stack()
146 : {
147 4198 : ExportedFunctionBase::create_parameter_stack<TFunc>();
148 4198 : m_customReturn = func_traits<TFunc>::custom_return;
149 : }
150 :
151 : /// returns the class name this method belongs to
152 : const std::string& class_name() const {return m_className;}
153 :
154 : /// returns true if this method handles its own return of values to lua
155 0 : bool has_custom_return() const {return m_customReturn;}
156 :
157 : private:
158 : /// pointer to function (stored in a wrapper)
159 : MethodPtrWrapper m_ptrWrapper;
160 :
161 : /// proxy function to call method
162 : ProxyFunc m_proxy_func;
163 :
164 : /// name of class this method belongs to
165 : std::string m_className;
166 :
167 : bool m_customReturn;
168 :
169 : #ifdef PROFILE_BRIDGE
170 : mutable RuntimeProfileInfo m_dpi;
171 : #endif
172 : };
173 :
174 : ////////////////////////////////////////////////////////////////////////////////
175 : // ExportedMethodGroup (sreiter)
176 : ////////////////////////////////////////////////////////////////////////////////
177 :
178 : /// Groups of methods - useful to realize overloaded methods
179 : class ExportedMethodGroup
180 : {
181 : typedef ExportedMethod::ProxyFunc ProxyFunc;
182 :
183 : public:
184 3354 : ExportedMethodGroup(const std::string& name) : m_name(name)
185 : {}
186 :
187 3354 : ~ExportedMethodGroup()
188 : {
189 7552 : for(size_t i = 0; i < m_overloads.size(); ++i)
190 4198 : delete m_overloads[i].m_func;
191 3354 : }
192 :
193 : /// name of function group
194 15860 : const std::string& name() const {return m_name;}
195 :
196 : /// adds an overload. Returns false if the overload already existed.
197 : template <class TFunc>
198 4198 : bool add_overload( const TFunc& m, ProxyFunc pf,
199 : const std::string& className,
200 : const std::string& methodOptions, const std::string& retValInfos,
201 : const std::string& paramInfos, const std::string& tooltip,
202 : const std::string& help)
203 : {
204 4198 : size_t typeID = GetUniqueTypeID<TFunc>();
205 :
206 : // make sure that the overload didn't exist
207 4198 : if(get_overload_by_type_id(typeID))
208 : return false;
209 :
210 : // create a new overload
211 8396 : ExportedMethod* func = new ExportedMethod(MethodPtrWrapper(m),
212 4198 : pf, m_name, className,
213 : methodOptions, retValInfos,
214 : paramInfos, tooltip, help);
215 :
216 4198 : m_overloads.push_back(Overload(func, typeID));
217 :
218 :
219 : // create parameter in list
220 : func->create_parameter_stack<TFunc>();
221 :
222 4198 : return true;
223 : }
224 :
225 : size_t num_overloads() const {return m_overloads.size();}
226 :
227 0 : ExportedMethod* get_overload(size_t index) {return m_overloads.at(index).m_func;}
228 :
229 0 : const ExportedMethod* get_overload(size_t index) const {return m_overloads.at(index).m_func;}
230 :
231 : template <class TType>
232 : ExportedMethod* get_overload_by_type()
233 : {
234 : size_t typeID = GetUniqueTypeID<TType>();
235 : return get_overload_by_type_id(typeID);
236 : }
237 :
238 : template <class TType>
239 : const ExportedMethod* get_overload_by_type() const
240 : {
241 : size_t typeID = GetUniqueTypeID<TType>();
242 : return get_overload_by_type_id(typeID);
243 : }
244 :
245 : ExportedMethod* get_overload_by_type_id(size_t typeID)
246 : {
247 7001 : for(size_t i = 0; i < m_overloads.size(); ++i){
248 2803 : if(m_overloads[i].m_typeID == typeID)
249 0 : return m_overloads[i].m_func;
250 : }
251 : return NULL;
252 : }
253 :
254 : const ExportedMethod* get_overload_by_type_id(size_t typeID) const
255 : {
256 : for(size_t i = 0; i < m_overloads.size(); ++i){
257 : if(m_overloads[i].m_typeID == typeID)
258 : return m_overloads[i].m_func;
259 : }
260 : return NULL;
261 : }
262 :
263 : size_t get_overload_type_id(size_t index) const {return m_overloads.at(index).m_typeID;}
264 :
265 : private:
266 : struct Overload{
267 : Overload() {}
268 : Overload(ExportedMethod* func, size_t typeID)
269 4198 : : m_func(func), m_typeID(typeID)
270 : {}
271 : ExportedMethod* m_func;
272 : size_t m_typeID;
273 : };
274 :
275 : std::string m_name;
276 : std::vector<Overload> m_overloads;
277 : };
278 :
279 : template <typename TClass, typename TMethod,
280 : typename TRet = typename func_traits<TMethod>::return_type>
281 : struct MethodProxy
282 : {
283 0 : static void apply(const MethodPtrWrapper& method, void* obj,
284 : const ParameterStack& in, ParameterStack& out)
285 : {
286 : // cast to method pointer
287 0 : TMethod mptr = *(TMethod*) method.get_raw_ptr();
288 :
289 : // cast object to type
290 : TClass* objPtr = (TClass*) (obj);
291 :
292 : // get parameter
293 : typedef typename func_traits<TMethod>::params_type params_type;
294 0 : ParameterStackToTypeValueList<params_type> args(in);
295 :
296 : // apply method
297 0 : TRet res = func_traits<TMethod>::apply(mptr, objPtr, args);
298 :
299 : // write return value
300 0 : out.push<TRet>(res);
301 0 : }
302 : };
303 :
304 : template <typename TClass, typename TMethod>
305 : struct MethodProxy<TClass, TMethod, void>
306 : {
307 0 : static void apply(const MethodPtrWrapper& method, void* obj,
308 : const ParameterStack& in, ParameterStack& out)
309 : {
310 : // cast to method pointer
311 0 : TMethod mptr = *(TMethod*) method.get_raw_ptr();
312 :
313 : // cast object to type
314 : TClass* objPtr = (TClass*) (obj);
315 :
316 : // get parameter
317 : typedef typename func_traits<TMethod>::params_type params_type;
318 0 : ParameterStackToTypeValueList<params_type> args(in);
319 :
320 : // apply method
321 0 : func_traits<TMethod>::apply(mptr, objPtr, args);
322 0 : }
323 : };
324 :
325 : template <typename TClass, typename TMethod>
326 : struct MethodProxy<TClass, TMethod, CustomReturn>
327 : {
328 : static void apply(const MethodPtrWrapper& method, void* obj,
329 : const ParameterStack& in, ParameterStack& out)
330 : {
331 : // cast to method pointer
332 : TMethod mptr = *(TMethod*) method.get_raw_ptr();
333 :
334 : // cast object to type
335 : TClass* objPtr = (TClass*) (obj);
336 :
337 : // get parameter
338 : typedef typename func_traits<TMethod>::params_type params_type;
339 : ParameterStackToTypeValueList<params_type> args(in);
340 :
341 : // apply method
342 : func_traits<TMethod>::apply(mptr, objPtr, args);
343 : }
344 : };
345 :
346 :
347 : ////////////////////////////////////////////////////////////////////////////////
348 : // Exported Constructor
349 : ////////////////////////////////////////////////////////////////////////////////
350 :
351 : /// describing information for constructor
352 : class UG_API ExportedConstructor
353 : {
354 : public:
355 : // all c++ functions are wrapped by a proxy function of the following type
356 : typedef void* (*ProxyFunc)(const ParameterStack& in);
357 :
358 : public:
359 : ExportedConstructor(ProxyFunc pf,
360 : const std::string& className, const std::string& options,
361 : const std::string& paramInfos,
362 : const std::string& tooltip, const std::string& help);
363 :
364 : /// executes the function
365 : void* create(const ParameterStack& paramsIn) const
366 : {
367 : #ifdef PROFILE_BRIDGE
368 : m_dpi.beginNode();
369 : #endif
370 :
371 0 : void *pRet = m_proxy_func(paramsIn);
372 :
373 : #ifdef PROFILE_BRIDGE
374 : m_dpi.endNode();
375 : #endif
376 : return pRet;
377 : }
378 :
379 : /// options
380 : const std::string& options() const {return m_options;}
381 :
382 : /// number of parameters.
383 : size_t num_parameter() const {return m_vvParamInfo.size();}
384 :
385 : /// number of info strings for one parameter
386 : size_t num_infos(size_t i) const {return m_vvParamInfo.at(i).size();}
387 :
388 : /// name of parameter i
389 0 : const std::string& parameter_name(size_t i) const {return parameter_info(i, 0);}
390 :
391 : /// type info of all parameters
392 0 : const std::string& parameter_info(size_t i, size_t j) const {return m_vvParamInfo.at(i).at(j);}
393 :
394 : /// type info of i th parameters
395 : const std::vector<std::string>& parameter_info_vec(size_t i) const {return m_vvParamInfo.at(i);}
396 :
397 : /// whole string of all type infos for of all parameters
398 : const std::string& parameter_info_string() const {return m_paramInfos;}
399 :
400 : /// gives some information to the exported functions
401 : const std::string& tooltip() const {return m_tooltip;}
402 :
403 : /// help informations
404 : const std::string& help() const {return m_help;}
405 :
406 : /// parameter list for input values
407 0 : const ParameterInfo& params_in() const {return m_paramsIn;}
408 :
409 : /// non-const export of param list
410 : ParameterInfo& params_in() {return m_paramsIn;}
411 :
412 : /// returns true if all parameters of the function are correctly declared
413 : bool check_consistency(std::string classname) const;
414 :
415 : template <typename TFunc>
416 1727 : void create_parameter_stack()
417 : {
418 : typedef typename func_traits<TFunc>::params_type params_type;
419 311 : CreateParameterInfo<params_type>::create(m_paramsIn);
420 :
421 : // arbitrary choosen minimum number of infos exported
422 : // (If values non given we set them to an empty string)
423 : const size_t MinNumInfos = 3; // for "name | style | options"
424 :
425 : // Fill missing Parameter
426 1727 : m_vvParamInfo.resize(m_paramsIn.size());
427 :
428 : // resize missing infos for each parameter
429 4059 : for(int i = 0; i < (int)m_vvParamInfo.size(); ++i)
430 7762 : for(size_t j = m_vvParamInfo.at(i).size(); j < MinNumInfos; ++j)
431 10860 : m_vvParamInfo.at(i).push_back(std::string(""));
432 1727 : }
433 :
434 : protected:
435 : // help function to tokenize the parameter string
436 : void tokenize(const std::string& str, std::vector<std::string>& tokens,
437 : const char delimiter);
438 :
439 : protected:
440 : private:
441 : /// proxy function to call method
442 : ProxyFunc m_proxy_func;
443 :
444 : /// name of class constructed
445 : std::string m_className;
446 :
447 : /// options
448 : std::string m_options;
449 :
450 : /// string with Infos about parameter
451 : std::string m_paramInfos;
452 :
453 : /// tokenized strings for each Parameter and each Info (name | style | options | ...)
454 : std::vector<std::vector<std::string> > m_vvParamInfo;
455 :
456 : std::string m_tooltip;
457 : std::string m_help;
458 :
459 : ParameterInfo m_paramsIn;
460 :
461 : #ifdef PROFILE_BRIDGE
462 : mutable RuntimeProfileInfo m_dpi;
463 : #endif
464 : };
465 :
466 : template <typename TClass, typename TMethod>
467 : struct ConstructorProxy
468 : {
469 0 : static void* create(const ParameterStack& in)
470 : {
471 : // get parameter
472 : typedef typename func_traits<TMethod>::params_type params_type;
473 0 : ParameterStackToTypeValueList<params_type> args(in);
474 :
475 : // apply method
476 0 : TClass* newInst = constructor_traits<TClass, params_type>::apply(args);
477 :
478 : // return new pointer
479 0 : return (void*) newInst;
480 : }
481 : };
482 :
483 : template <typename TClass>
484 0 : void DestructorProxy(void* obj)
485 : {
486 : TClass* pObj = (TClass*)obj;
487 0 : delete pObj;
488 0 : }
489 :
490 : ////////////////////////////////////////////////////////////////////////////////
491 : // Interface Exported Class
492 : ////////////////////////////////////////////////////////////////////////////////
493 :
494 :
495 : class JSONConstructible {};
496 :
497 : /// Base class for exported Classes
498 : class IExportedClass
499 : {
500 : public:
501 : typedef void (*DeleteFunction)(const void*);
502 :
503 : public:
504 : /// name of class
505 : virtual const std::string& name() const = 0;
506 :
507 : /// get groups
508 : virtual const std::string& group() const = 0;
509 :
510 : /// name node of class
511 : virtual const ClassNameNode& class_name_node() const = 0;
512 :
513 : /// get tooltip
514 : virtual const std::string& tooltip() const = 0;
515 :
516 : /// name-list of class hierarchy
517 : virtual const std::vector<const char*>* class_names() const = 0;
518 :
519 : /// number of method of the class
520 : virtual size_t num_methods() const = 0;
521 :
522 : /// number of registered const-methods
523 : virtual size_t num_const_methods() const = 0;
524 :
525 : /// get exported method
526 : virtual const ExportedMethod& get_method(size_t i) const = 0;
527 :
528 : /// get exported const-method
529 : virtual const ExportedMethod& get_const_method(size_t i) const = 0;
530 :
531 : /// returns the number of overloads of a method
532 : virtual size_t num_overloads(size_t funcInd) const = 0;
533 :
534 : /// returns the number of overloads of a const method
535 : virtual size_t num_const_overloads(size_t funcInd) const = 0;
536 :
537 : /// returns the i-th overload of a method
538 : virtual const ExportedMethod& get_overload(size_t funcInd, size_t oInd) const = 0;
539 :
540 : /// returns the i-th overload of a const method
541 : virtual const ExportedMethod& get_const_overload(size_t funcInd, size_t oInd) const = 0;
542 :
543 : /// returns the i-th method group (all overloads of the i-th function)
544 : virtual const ExportedMethodGroup& get_method_group(size_t ind) const = 0;
545 :
546 : /// returns the i-th method group (all overloads of the i-th function)
547 : virtual const ExportedMethodGroup& get_const_method_group(size_t ind) const = 0;
548 :
549 : virtual const ExportedMethodGroup* get_exported_method_group(const std::string& name) const = 0;
550 :
551 : virtual const ExportedMethodGroup* get_const_exported_method_group(const std::string& name) const = 0;
552 :
553 : /** can we create instances of this class
554 : * (i.e. the class does not contain pure virtual functions)*/
555 : virtual bool is_instantiable() const = 0;
556 :
557 : /// number of registered constructors
558 : virtual size_t num_constructors() const = 0;
559 :
560 : /// get exported constructor
561 : virtual const ExportedConstructor& get_constructor(size_t i) const = 0;
562 :
563 : /// get constructor for construction from json
564 : virtual const boost::optional<ExportedConstructor&> get_json_constructor() const = 0;
565 :
566 : /// get constructor for construction from json
567 : virtual bool is_json_constructible() const = 0;
568 :
569 : /// true if the class shall be wrapped in a SmartPtr on construction
570 : virtual bool construct_as_smart_pointer() const = 0;
571 :
572 : /// destructur for object
573 : virtual void destroy(void* obj) const = 0;
574 :
575 : /// returns a function which will call delete on the object
576 : virtual DeleteFunction get_delete_function() const = 0;
577 :
578 : /// returns false is consistency-check failed
579 : virtual bool check_consistency() const;
580 :
581 : /// virtual destructor
582 : virtual ~IExportedClass() {};
583 : };
584 :
585 : /// A base implementation with non-template methods.
586 : /** Speeds up compilation times.*/
587 : class ExportedClassBaseImpl : public IExportedClass
588 : {
589 : private:
590 : // disallow
591 : ExportedClassBaseImpl();
592 : ExportedClassBaseImpl(const ExportedClassBaseImpl& other);
593 :
594 : public:
595 : ExportedClassBaseImpl(const std::string& tooltip);
596 :
597 : /// destructor
598 : virtual ~ExportedClassBaseImpl();
599 :
600 : /// tooltip
601 : virtual const std::string& tooltip() const;
602 :
603 : /// number of registered methods (overloads are not counted)
604 : virtual size_t num_methods() const;
605 :
606 : /// number of registered const-methods (overloads are not counted)
607 : virtual size_t num_const_methods() const;
608 :
609 : /// returns the first overload of an exported function
610 : virtual const ExportedMethod& get_method(size_t i) const;
611 :
612 : /// returns the first overload of an exported const function
613 : virtual const ExportedMethod& get_const_method(size_t i) const;
614 :
615 : /// returns the number of overloads of a method
616 : virtual size_t num_overloads(size_t funcInd) const;
617 :
618 : /// returns the number of overloads of a const method
619 : virtual size_t num_const_overloads(size_t funcInd) const;
620 :
621 : /// returns the i-th overload of a method
622 : virtual const ExportedMethod& get_overload(size_t funcInd, size_t oInd) const;
623 :
624 : /// returns the i-th overload of a const method
625 : virtual const ExportedMethod& get_const_overload(size_t funcInd, size_t oInd) const;
626 :
627 : /// returns the i-th method group (all overloads of the i-th function)
628 : virtual const ExportedMethodGroup& get_method_group(size_t ind) const;
629 :
630 : /// returns the i-th method group (all overloads of the i-th function)
631 : virtual const ExportedMethodGroup& get_const_method_group(size_t ind) const;
632 :
633 : virtual const ExportedMethodGroup* get_exported_method_group(const std::string& name) const;
634 :
635 : virtual const ExportedMethodGroup* get_const_exported_method_group(const std::string& name) const;
636 :
637 : /// number of registered constructors
638 : virtual size_t num_constructors() const;
639 :
640 : /// get exported constructor
641 : virtual const ExportedConstructor& get_constructor(size_t i) const;
642 :
643 : /// get constructor for construction from json
644 : virtual const boost::optional<ExportedConstructor&> get_json_constructor() const;
645 :
646 : /// returns whether the class shall be wrapped in a SmartPtr on construction
647 : virtual bool construct_as_smart_pointer() const;
648 :
649 : /// sets whether the class shall be wrapped in a SmartPtr
650 : /** Returns a reference to this, so that it can be used in a chained call.*/
651 : virtual void set_construct_as_smart_pointer(bool enable);
652 :
653 : /// is instantiable
654 : virtual bool is_instantiable() const;
655 :
656 : /// destructur for object
657 : virtual void destroy(void* obj) const;
658 :
659 : protected:
660 : /// returns if a constructor overload is registered
661 : bool constructor_type_id_registered(size_t typeID);
662 :
663 : /// returns true if methodname is already used by a method in this class
664 : bool constmethodname_registered(const std::string& name);
665 :
666 : /// returns true if methodname is already used by a method in this class
667 : bool methodname_registered(const std::string& name);
668 :
669 : ExportedMethodGroup* get_exported_method_group(const std::string& name);
670 :
671 : ExportedMethodGroup* get_const_exported_method_group(const std::string& name);
672 :
673 : protected:
674 : struct ConstructorOverload{
675 : ConstructorOverload() {}
676 : ConstructorOverload(ExportedConstructor* func, size_t typeID)
677 1727 : : m_constructor(func), m_typeID(typeID)
678 : {}
679 : ExportedConstructor* m_constructor;
680 : size_t m_typeID;
681 : };
682 :
683 : std::vector<ConstructorOverload> m_vConstructor;
684 :
685 : typedef void (*DestructorFunc)(void*);
686 : DestructorFunc m_destructor;
687 :
688 : std::vector<ExportedMethodGroup*> m_vMethod;
689 : std::vector<ExportedMethodGroup*> m_vConstMethod;
690 : std::string m_tooltip;
691 :
692 : bool m_constructAsSmartPtr;
693 : };
694 :
695 :
696 : /// This template class represents real c++ classes in the registry.
697 : template <typename TClass>
698 : class ExportedClass : public ExportedClassBaseImpl
699 : {
700 : private:
701 : // disallow
702 : ExportedClass () {};
703 : ExportedClass (const ExportedClass& other);
704 :
705 : public:
706 : // contructor
707 1349 : ExportedClass(const std::string& name, const std::string& group,
708 : const std::string& tooltip)
709 1349 : : ExportedClassBaseImpl(tooltip)
710 : {
711 1349 : ClassNameProvider<TClass>::set_name(name, group, true);
712 1349 : ClassNameProvider<const TClass>::set_name(name, group, true);
713 1349 : }
714 :
715 : /// destructor
716 1349 : virtual ~ExportedClass(){}
717 :
718 : /// name of class
719 3466425 : virtual const std::string& name() const {return ClassNameProvider<TClass>::name();}
720 :
721 : /// name node of class
722 0 : virtual const ClassNameNode& class_name_node() const {return ClassNameProvider<TClass>::class_name_node();}
723 :
724 : /// get groups
725 0 : virtual const std::string& group() const {return ClassNameProvider<TClass>::group();}
726 :
727 : /// is json constructible
728 0 : virtual bool is_json_constructible() const { return std::is_base_of<JSONConstructible, TClass>::value; }
729 :
730 : //\todo: remove this method, use class name nodes instead
731 : /// class-hierarchy
732 0 : virtual const std::vector<const char*>* class_names() const {return &ClassNameProvider<TClass>::names();}
733 :
734 : template<typename T>
735 : ExportedClass<TClass>& add_(T t)
736 : {
737 : return t.add_to(*this);
738 : }
739 : /// Method registration
740 : /**
741 : * @param methodName the name of the method to appear in the registry
742 : * @param func pointer to the member function (e.g. &MyClass::my_method)
743 : * @param retValInfos string documenting what the function returns (optional)
744 : * @param paramInfos string documenting the parameters of the function
745 : * seperate parameters with an # e.g. "x#y#z" (don't specify the type of the values) (optional)
746 : * @param toolTip small documentation for the function (optional)
747 : * @param help help string for the function
748 : * @sa \ref pageUG4Registry
749 : * @sa \ref secSTHowToSpecifyParameterInformation
750 : */
751 : template <typename TMethod>
752 4198 : ExportedClass<TClass>& add_method (std::string methodName, TMethod func,
753 : std::string retValInfos = "", std::string paramInfos = "",
754 : std::string tooltip = "", std::string help = "")
755 : {
756 : // At this point the method name contains parameters (name|param1=...).
757 : //todo: they should be removed and specified with an extra parameter.
758 :
759 : std::string strippedMethodName = methodName;
760 : std::string methodOptions;
761 : std::string::size_type pos = strippedMethodName.find("|");
762 4198 : if(pos != std::string::npos){
763 15 : methodOptions = strippedMethodName.substr(pos + 1, strippedMethodName.length() - pos);
764 30 : strippedMethodName = strippedMethodName.substr(0, pos);
765 : }
766 :
767 : // trim whitespaces
768 4198 : strippedMethodName = TrimString(strippedMethodName);
769 8396 : methodOptions = TrimString(methodOptions);
770 :
771 : // check that name is not empty
772 4198 : if(strippedMethodName.empty())
773 : {
774 0 : UG_THROW_REGISTRY_ERROR(strippedMethodName,
775 : "Trying to register empty method name.");
776 : }
777 :
778 : // check that name does not contain illegal characters
779 4198 : if (!IsValidRegistryIdentifier(strippedMethodName)) {
780 0 : UG_THROW_REGISTRY_ERROR(strippedMethodName,
781 : "Trying to register method '"<< strippedMethodName << "' that"
782 : << " contains illegal characters. "
783 : << GetRegistryIdentifierMessage());
784 : }
785 :
786 : // if the method is already in use, we have to add an overload.
787 : // If not, we have to create a new method group
788 : ExportedMethodGroup* methodGrp = NULL;
789 : if(func_traits<TMethod>::const_method)
790 620 : methodGrp = get_const_exported_method_group(strippedMethodName);
791 : else
792 3578 : methodGrp = get_exported_method_group(strippedMethodName);
793 :
794 4198 : if(!methodGrp){
795 3354 : methodGrp = new ExportedMethodGroup(strippedMethodName);
796 : if(func_traits<TMethod>::const_method)
797 595 : m_vConstMethod.push_back(methodGrp);
798 : else
799 2759 : m_vMethod.push_back(methodGrp);
800 : }
801 :
802 4198 : bool success = methodGrp->add_overload(func, &MethodProxy<TClass, TMethod>::apply,
803 : ClassNameProvider<TClass>::name(),
804 : methodOptions, retValInfos, paramInfos,
805 : tooltip, help);
806 :
807 4198 : if(!success)
808 : {
809 0 : UG_THROW_REGISTRY_ERROR(name(),
810 : "Trying to register method name '" << strippedMethodName
811 : << "' to class '" << name() << "', but another method with this name "
812 : << " and the same function signature is already registered for this class.");
813 : }
814 :
815 4198 : return *this;
816 : }
817 :
818 : /// Make default constructor accessible
819 446 : ExportedClass<TClass>& add_constructor ()
820 : {
821 : // add also in new style
822 892 : add_constructor<void (*)()>();
823 :
824 : // remember constructor proxy
825 446 : m_destructor = &DestructorProxy<TClass>;
826 :
827 446 : return *this;
828 : }
829 :
830 : /// constructor registration
831 : /**
832 : * @param paramInfos string documenting the parameters of the function
833 : * seperate parameters with an # e.g. "x#y#z" (don't specify the type of the values) (optional)
834 : * @param toolTip small documentation for the function (optional)
835 : * @param help help string for the function
836 : * @param options style option of the constructor itself (for visualisation)
837 : * @sa \ref pageUG4Registry
838 : */
839 : template <typename TFunc>
840 1727 : ExportedClass<TClass>& add_constructor(std::string paramInfos = "",
841 : std::string tooltip = "", std::string help = "",
842 : std::string options = "")
843 : {
844 : // return-type must be void
845 : if(!(boost::is_void< typename func_traits<TFunc>::return_type >::value))
846 : {
847 : UG_THROW_REGISTRY_ERROR(name(),
848 : "Trying to register constructor of class "
849 : <<name()<<"with non-void return value in signature function.");
850 : }
851 :
852 : // type id of constructor
853 1727 : size_t typeID = GetUniqueTypeID<TFunc>();
854 :
855 : // make sure that the overload didn't exist
856 1727 : if(constructor_type_id_registered(typeID))
857 : {
858 0 : UG_THROW_REGISTRY_ERROR(name(),
859 : "Trying to register constructor of class "
860 : <<name()<<" with same signature twice.");
861 : }
862 :
863 : // create new exported constructor
864 : ExportedConstructor* expConstr
865 3454 : = new ExportedConstructor( &ConstructorProxy<TClass, TFunc>::create,
866 : ClassNameProvider<TClass>::name(),
867 : options, paramInfos, tooltip, help);
868 :
869 : // create parameter stack
870 1727 : expConstr->create_parameter_stack<TFunc>();
871 :
872 : // rememeber it
873 1727 : m_vConstructor.push_back(ConstructorOverload(expConstr, typeID));
874 :
875 : // done
876 1727 : return *this;
877 : }
878 :
879 : /// return pointer to the delete method
880 0 : virtual DeleteFunction get_delete_function() const
881 : {
882 0 : return CastAndDelete<TClass>;
883 : }
884 : };
885 :
886 : // end group registry
887 : /// \}
888 :
889 : } // end namespace bridge
890 : } // end namespace ug
891 :
892 :
893 : #endif /* __H__UG_BRIDGE__CLASS__ */
|