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