1/**************************************************************************/
2/* method_bind.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef METHOD_BIND_H
32#define METHOD_BIND_H
33
34#include "core/variant/binder_common.h"
35
36VARIANT_BITFIELD_CAST(MethodFlags)
37
38// some helpers
39
40class MethodBind {
41 int method_id;
42 uint32_t hint_flags = METHOD_FLAGS_DEFAULT;
43 StringName name;
44 StringName instance_class;
45 Vector<Variant> default_arguments;
46 int default_argument_count = 0;
47 int argument_count = 0;
48
49 bool _static = false;
50 bool _const = false;
51 bool _returns = false;
52 bool _returns_raw_obj_ptr = false;
53
54protected:
55 Variant::Type *argument_types = nullptr;
56#ifdef DEBUG_METHODS_ENABLED
57 Vector<StringName> arg_names;
58#endif
59 void _set_const(bool p_const);
60 void _set_static(bool p_static);
61 void _set_returns(bool p_returns);
62 virtual Variant::Type _gen_argument_type(int p_arg) const = 0;
63 virtual PropertyInfo _gen_argument_type_info(int p_arg) const = 0;
64 void _generate_argument_types(int p_count);
65
66 void set_argument_count(int p_count) { argument_count = p_count; }
67
68public:
69 _FORCE_INLINE_ const Vector<Variant> &get_default_arguments() const { return default_arguments; }
70 _FORCE_INLINE_ int get_default_argument_count() const { return default_argument_count; }
71
72 _FORCE_INLINE_ Variant has_default_argument(int p_arg) const {
73 int idx = p_arg - (argument_count - default_arguments.size());
74
75 if (idx < 0 || idx >= default_arguments.size()) {
76 return false;
77 } else {
78 return true;
79 }
80 }
81
82 _FORCE_INLINE_ Variant get_default_argument(int p_arg) const {
83 int idx = p_arg - (argument_count - default_arguments.size());
84
85 if (idx < 0 || idx >= default_arguments.size()) {
86 return Variant();
87 } else {
88 return default_arguments[idx];
89 }
90 }
91
92 _FORCE_INLINE_ Variant::Type get_argument_type(int p_argument) const {
93 ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, Variant::NIL);
94 return argument_types[p_argument + 1];
95 }
96
97 PropertyInfo get_argument_info(int p_argument) const;
98 PropertyInfo get_return_info() const;
99
100#ifdef DEBUG_METHODS_ENABLED
101 void set_argument_names(const Vector<StringName> &p_names); // Set by ClassDB, can't be inferred otherwise.
102 Vector<StringName> get_argument_names() const;
103
104 virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const = 0;
105#endif
106
107 void set_hint_flags(uint32_t p_hint) { hint_flags = p_hint; }
108 uint32_t get_hint_flags() const { return hint_flags | (is_const() ? METHOD_FLAG_CONST : 0) | (is_vararg() ? METHOD_FLAG_VARARG : 0) | (is_static() ? METHOD_FLAG_STATIC : 0); }
109 _FORCE_INLINE_ StringName get_instance_class() const { return instance_class; }
110 _FORCE_INLINE_ void set_instance_class(const StringName &p_class) { instance_class = p_class; }
111
112 _FORCE_INLINE_ int get_argument_count() const { return argument_count; };
113
114 virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const = 0;
115 virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const = 0;
116
117 virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const = 0;
118
119 StringName get_name() const;
120 void set_name(const StringName &p_name);
121 _FORCE_INLINE_ int get_method_id() const { return method_id; }
122 _FORCE_INLINE_ bool is_const() const { return _const; }
123 _FORCE_INLINE_ bool is_static() const { return _static; }
124 _FORCE_INLINE_ bool has_return() const { return _returns; }
125 virtual bool is_vararg() const { return false; }
126
127 _FORCE_INLINE_ bool is_return_type_raw_object_ptr() { return _returns_raw_obj_ptr; }
128 _FORCE_INLINE_ void set_return_type_is_raw_object_ptr(bool p_returns_raw_obj) { _returns_raw_obj_ptr = p_returns_raw_obj; }
129
130 void set_default_arguments(const Vector<Variant> &p_defargs);
131
132 uint32_t get_hash() const;
133
134 MethodBind();
135 virtual ~MethodBind();
136};
137
138// MethodBindVarArg base CRTP
139template <class Derived, class T, class R, bool should_returns>
140class MethodBindVarArgBase : public MethodBind {
141protected:
142 R(T::*method)
143 (const Variant **, int, Callable::CallError &);
144 MethodInfo method_info;
145
146public:
147 virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
148 if (p_arg < 0) {
149 return _gen_return_type_info();
150 } else if (p_arg < method_info.arguments.size()) {
151 return method_info.arguments[p_arg];
152 } else {
153 return PropertyInfo(Variant::NIL, "arg_" + itos(p_arg), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
154 }
155 }
156
157 virtual Variant::Type _gen_argument_type(int p_arg) const override {
158 return _gen_argument_type_info(p_arg).type;
159 }
160
161#ifdef DEBUG_METHODS_ENABLED
162 virtual GodotTypeInfo::Metadata get_argument_meta(int) const override {
163 return GodotTypeInfo::METADATA_NONE;
164 }
165#endif
166
167 virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
168 ERR_FAIL_MSG("Validated call can't be used with vararg methods. This is a bug.");
169 }
170
171 virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
172 ERR_FAIL_MSG("ptrcall can't be used with vararg methods. This is a bug.");
173 }
174
175 virtual bool is_const() const { return false; }
176
177 virtual bool is_vararg() const override { return true; }
178
179 MethodBindVarArgBase(
180 R (T::*p_method)(const Variant **, int, Callable::CallError &),
181 const MethodInfo &p_method_info,
182 bool p_return_nil_is_variant) :
183 method(p_method), method_info(p_method_info) {
184 set_argument_count(method_info.arguments.size());
185 Variant::Type *at = memnew_arr(Variant::Type, method_info.arguments.size() + 1);
186 at[0] = _gen_return_type_info().type;
187 if (method_info.arguments.size()) {
188#ifdef DEBUG_METHODS_ENABLED
189 Vector<StringName> names;
190 names.resize(method_info.arguments.size());
191#endif
192 for (int i = 0; i < method_info.arguments.size(); i++) {
193 at[i + 1] = method_info.arguments[i].type;
194#ifdef DEBUG_METHODS_ENABLED
195 names.write[i] = method_info.arguments[i].name;
196#endif
197 }
198
199#ifdef DEBUG_METHODS_ENABLED
200 set_argument_names(names);
201#endif
202 }
203 argument_types = at;
204 if (p_return_nil_is_variant) {
205 method_info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
206 }
207
208 _set_returns(should_returns);
209 }
210
211private:
212 PropertyInfo _gen_return_type_info() const {
213 return Derived::_gen_return_type_info_impl();
214 }
215};
216
217// variadic, no return
218template <class T>
219class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false> {
220 friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>;
221
222public:
223 virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
224 (static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>::method)(p_args, p_arg_count, r_error);
225 return {};
226 }
227
228 MethodBindVarArgT(
229 void (T::*p_method)(const Variant **, int, Callable::CallError &),
230 const MethodInfo &p_method_info,
231 bool p_return_nil_is_variant) :
232 MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>(p_method, p_method_info, p_return_nil_is_variant) {
233 }
234
235private:
236 static PropertyInfo _gen_return_type_info_impl() {
237 return {};
238 }
239};
240
241template <class T>
242MethodBind *create_vararg_method_bind(void (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
243 MethodBind *a = memnew((MethodBindVarArgT<T>)(p_method, p_info, p_return_nil_is_variant));
244 a->set_instance_class(T::get_class_static());
245 return a;
246}
247
248// variadic, return
249template <class T, class R>
250class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true> {
251 friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>;
252
253public:
254#if defined(SANITIZERS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
255 // Workaround GH-66343 raised only with UBSAN, seems to be a false positive.
256#pragma GCC diagnostic push
257#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
258#endif
259 virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
260 return (static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>::method)(p_args, p_arg_count, r_error);
261 }
262
263#if defined(SANITIZERS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
264#pragma GCC diagnostic pop
265#endif
266
267 MethodBindVarArgTR(
268 R (T::*p_method)(const Variant **, int, Callable::CallError &),
269 const MethodInfo &p_info,
270 bool p_return_nil_is_variant) :
271 MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>(p_method, p_info, p_return_nil_is_variant) {
272 }
273
274private:
275 static PropertyInfo _gen_return_type_info_impl() {
276 return GetTypeInfo<R>::get_class_info();
277 }
278};
279
280template <class T, class R>
281MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
282 MethodBind *a = memnew((MethodBindVarArgTR<T, R>)(p_method, p_info, p_return_nil_is_variant));
283 a->set_instance_class(T::get_class_static());
284 return a;
285}
286
287/**** VARIADIC TEMPLATES ****/
288
289#ifndef TYPED_METHOD_BIND
290class __UnexistingClass;
291#define MB_T __UnexistingClass
292#else
293#define MB_T T
294#endif
295
296// no return, not const
297#ifdef TYPED_METHOD_BIND
298template <class T, class... P>
299#else
300template <class... P>
301#endif
302class MethodBindT : public MethodBind {
303 void (MB_T::*method)(P...);
304
305protected:
306 virtual Variant::Type _gen_argument_type(int p_arg) const override {
307 if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
308 return call_get_argument_type<P...>(p_arg);
309 } else {
310 return Variant::NIL;
311 }
312 }
313
314 virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
315 PropertyInfo pi;
316 call_get_argument_type_info<P...>(p_arg, pi);
317 return pi;
318 }
319
320public:
321#ifdef DEBUG_METHODS_ENABLED
322 virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
323 return call_get_argument_metadata<P...>(p_arg);
324 }
325
326#endif
327 virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
328#ifdef TYPED_METHOD_BIND
329 call_with_variant_args_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments());
330#else
331 call_with_variant_args_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments());
332#endif
333 return Variant();
334 }
335
336 virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
337#ifdef TYPED_METHOD_BIND
338 call_with_validated_object_instance_args(static_cast<T *>(p_object), method, p_args);
339#else
340 call_with_validated_object_instance_args(reinterpret_cast<MB_T *>(p_object), method, p_args);
341#endif
342 }
343
344 virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
345#ifdef TYPED_METHOD_BIND
346 call_with_ptr_args<T, P...>(static_cast<T *>(p_object), method, p_args);
347#else
348 call_with_ptr_args<MB_T, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args);
349#endif
350 }
351
352 MethodBindT(void (MB_T::*p_method)(P...)) {
353 method = p_method;
354 _generate_argument_types(sizeof...(P));
355 set_argument_count(sizeof...(P));
356 }
357};
358
359template <class T, class... P>
360MethodBind *create_method_bind(void (T::*p_method)(P...)) {
361#ifdef TYPED_METHOD_BIND
362 MethodBind *a = memnew((MethodBindT<T, P...>)(p_method));
363#else
364 MethodBind *a = memnew((MethodBindT<P...>)(reinterpret_cast<void (MB_T::*)(P...)>(p_method)));
365#endif
366 a->set_instance_class(T::get_class_static());
367 return a;
368}
369
370// no return, const
371
372#ifdef TYPED_METHOD_BIND
373template <class T, class... P>
374#else
375template <class... P>
376#endif
377class MethodBindTC : public MethodBind {
378 void (MB_T::*method)(P...) const;
379
380protected:
381 virtual Variant::Type _gen_argument_type(int p_arg) const override {
382 if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
383 return call_get_argument_type<P...>(p_arg);
384 } else {
385 return Variant::NIL;
386 }
387 }
388
389 virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
390 PropertyInfo pi;
391 call_get_argument_type_info<P...>(p_arg, pi);
392 return pi;
393 }
394
395public:
396#ifdef DEBUG_METHODS_ENABLED
397 virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
398 return call_get_argument_metadata<P...>(p_arg);
399 }
400
401#endif
402 virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
403#ifdef TYPED_METHOD_BIND
404 call_with_variant_argsc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments());
405#else
406 call_with_variant_argsc_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments());
407#endif
408 return Variant();
409 }
410
411 virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
412#ifdef TYPED_METHOD_BIND
413 call_with_validated_object_instance_argsc(static_cast<T *>(p_object), method, p_args);
414#else
415 call_with_validated_object_instance_argsc(reinterpret_cast<MB_T *>(p_object), method, p_args);
416#endif
417 }
418
419 virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
420#ifdef TYPED_METHOD_BIND
421 call_with_ptr_argsc<T, P...>(static_cast<T *>(p_object), method, p_args);
422#else
423 call_with_ptr_argsc<MB_T, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args);
424#endif
425 }
426
427 MethodBindTC(void (MB_T::*p_method)(P...) const) {
428 method = p_method;
429 _set_const(true);
430 _generate_argument_types(sizeof...(P));
431 set_argument_count(sizeof...(P));
432 }
433};
434
435template <class T, class... P>
436MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
437#ifdef TYPED_METHOD_BIND
438 MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method));
439#else
440 MethodBind *a = memnew((MethodBindTC<P...>)(reinterpret_cast<void (MB_T::*)(P...) const>(p_method)));
441#endif
442 a->set_instance_class(T::get_class_static());
443 return a;
444}
445
446// return, not const
447
448#ifdef TYPED_METHOD_BIND
449template <class T, class R, class... P>
450#else
451template <class R, class... P>
452#endif
453class MethodBindTR : public MethodBind {
454 R(MB_T::*method)
455 (P...);
456
457protected:
458 virtual Variant::Type _gen_argument_type(int p_arg) const override {
459 if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
460 return call_get_argument_type<P...>(p_arg);
461 } else {
462 return GetTypeInfo<R>::VARIANT_TYPE;
463 }
464 }
465
466 virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
467 if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
468 PropertyInfo pi;
469 call_get_argument_type_info<P...>(p_arg, pi);
470 return pi;
471 } else {
472 return GetTypeInfo<R>::get_class_info();
473 }
474 }
475
476public:
477#ifdef DEBUG_METHODS_ENABLED
478 virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
479 if (p_arg >= 0) {
480 return call_get_argument_metadata<P...>(p_arg);
481 } else {
482 return GetTypeInfo<R>::METADATA;
483 }
484 }
485#endif
486
487 virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
488 Variant ret;
489#ifdef TYPED_METHOD_BIND
490 call_with_variant_args_ret_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments());
491#else
492 call_with_variant_args_ret_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments());
493#endif
494 return ret;
495 }
496
497 virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
498#ifdef TYPED_METHOD_BIND
499 call_with_validated_object_instance_args_ret(static_cast<T *>(p_object), method, p_args, r_ret);
500#else
501 call_with_validated_object_instance_args_ret(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret);
502#endif
503 }
504
505 virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
506#ifdef TYPED_METHOD_BIND
507 call_with_ptr_args_ret<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret);
508#else
509 call_with_ptr_args_ret<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret);
510#endif
511 }
512
513 MethodBindTR(R (MB_T::*p_method)(P...)) {
514 method = p_method;
515 _set_returns(true);
516 _generate_argument_types(sizeof...(P));
517 set_argument_count(sizeof...(P));
518 }
519};
520
521template <class T, class R, class... P>
522MethodBind *create_method_bind(R (T::*p_method)(P...)) {
523#ifdef TYPED_METHOD_BIND
524 MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method));
525#else
526 MethodBind *a = memnew((MethodBindTR<R, P...>)(reinterpret_cast<R (MB_T::*)(P...)>(p_method)));
527#endif
528
529 a->set_instance_class(T::get_class_static());
530 return a;
531}
532
533// return, const
534
535#ifdef TYPED_METHOD_BIND
536template <class T, class R, class... P>
537#else
538template <class R, class... P>
539#endif
540class MethodBindTRC : public MethodBind {
541 R(MB_T::*method)
542 (P...) const;
543
544protected:
545 virtual Variant::Type _gen_argument_type(int p_arg) const override {
546 if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
547 return call_get_argument_type<P...>(p_arg);
548 } else {
549 return GetTypeInfo<R>::VARIANT_TYPE;
550 }
551 }
552
553 virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
554 if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
555 PropertyInfo pi;
556 call_get_argument_type_info<P...>(p_arg, pi);
557 return pi;
558 } else {
559 return GetTypeInfo<R>::get_class_info();
560 }
561 }
562
563public:
564#ifdef DEBUG_METHODS_ENABLED
565 virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
566 if (p_arg >= 0) {
567 return call_get_argument_metadata<P...>(p_arg);
568 } else {
569 return GetTypeInfo<R>::METADATA;
570 }
571 }
572#endif
573
574 virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
575 Variant ret;
576#ifdef TYPED_METHOD_BIND
577 call_with_variant_args_retc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments());
578#else
579 call_with_variant_args_retc_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments());
580#endif
581 return ret;
582 }
583
584 virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
585#ifdef TYPED_METHOD_BIND
586 call_with_validated_object_instance_args_retc(static_cast<T *>(p_object), method, p_args, r_ret);
587#else
588 call_with_validated_object_instance_args_retc(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret);
589#endif
590 }
591
592 virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
593#ifdef TYPED_METHOD_BIND
594 call_with_ptr_args_retc<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret);
595#else
596 call_with_ptr_args_retc<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret);
597#endif
598 }
599
600 MethodBindTRC(R (MB_T::*p_method)(P...) const) {
601 method = p_method;
602 _set_returns(true);
603 _set_const(true);
604 _generate_argument_types(sizeof...(P));
605 set_argument_count(sizeof...(P));
606 }
607};
608
609template <class T, class R, class... P>
610MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
611#ifdef TYPED_METHOD_BIND
612 MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method));
613#else
614 MethodBind *a = memnew((MethodBindTRC<R, P...>)(reinterpret_cast<R (MB_T::*)(P...) const>(p_method)));
615#endif
616 a->set_instance_class(T::get_class_static());
617 return a;
618}
619
620/* STATIC BINDS */
621
622// no return
623
624template <class... P>
625class MethodBindTS : public MethodBind {
626 void (*function)(P...);
627
628protected:
629 virtual Variant::Type _gen_argument_type(int p_arg) const override {
630 if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
631 return call_get_argument_type<P...>(p_arg);
632 } else {
633 return Variant::NIL;
634 }
635 }
636
637 virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
638 PropertyInfo pi;
639 call_get_argument_type_info<P...>(p_arg, pi);
640 return pi;
641 }
642
643public:
644#ifdef DEBUG_METHODS_ENABLED
645 virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
646 return call_get_argument_metadata<P...>(p_arg);
647 }
648
649#endif
650 virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
651 (void)p_object; // unused
652 call_with_variant_args_static_dv(function, p_args, p_arg_count, r_error, get_default_arguments());
653 return Variant();
654 }
655
656 virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
657 call_with_validated_variant_args_static_method(function, p_args);
658 }
659
660 virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
661 (void)p_object;
662 (void)r_ret;
663 call_with_ptr_args_static_method(function, p_args);
664 }
665
666 MethodBindTS(void (*p_function)(P...)) {
667 function = p_function;
668 _generate_argument_types(sizeof...(P));
669 set_argument_count(sizeof...(P));
670 _set_static(true);
671 }
672};
673
674template <class... P>
675MethodBind *create_static_method_bind(void (*p_method)(P...)) {
676 MethodBind *a = memnew((MethodBindTS<P...>)(p_method));
677 return a;
678}
679
680// return
681
682template <class R, class... P>
683class MethodBindTRS : public MethodBind {
684 R(*function)
685 (P...);
686
687protected:
688 virtual Variant::Type _gen_argument_type(int p_arg) const override {
689 if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
690 return call_get_argument_type<P...>(p_arg);
691 } else {
692 return GetTypeInfo<R>::VARIANT_TYPE;
693 }
694 }
695
696 virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
697 if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
698 PropertyInfo pi;
699 call_get_argument_type_info<P...>(p_arg, pi);
700 return pi;
701 } else {
702 return GetTypeInfo<R>::get_class_info();
703 }
704 }
705
706public:
707#ifdef DEBUG_METHODS_ENABLED
708 virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
709 if (p_arg >= 0) {
710 return call_get_argument_metadata<P...>(p_arg);
711 } else {
712 return GetTypeInfo<R>::METADATA;
713 }
714 }
715
716#endif
717 virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
718 Variant ret;
719 call_with_variant_args_static_ret_dv(function, p_args, p_arg_count, ret, r_error, get_default_arguments());
720 return ret;
721 }
722
723 virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
724 call_with_validated_variant_args_static_method_ret(function, p_args, r_ret);
725 }
726
727 virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
728 (void)p_object;
729 call_with_ptr_args_static_method_ret(function, p_args, r_ret);
730 }
731
732 MethodBindTRS(R (*p_function)(P...)) {
733 function = p_function;
734 _generate_argument_types(sizeof...(P));
735 set_argument_count(sizeof...(P));
736 _set_static(true);
737 _set_returns(true);
738 }
739};
740
741template <class R, class... P>
742MethodBind *create_static_method_bind(R (*p_method)(P...)) {
743 MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method));
744 return a;
745}
746
747#endif // METHOD_BIND_H
748