Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/object/method_bind_common.h
45997 views
1
/**************************************************************************/
2
/* method_bind_common.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
#pragma once
32
33
#include "core/object/method_bind.h"
34
#include "core/variant/binder_common.h"
35
36
VARIANT_BITFIELD_CAST(MethodFlags)
37
38
/**** VARIADIC TEMPLATES ****/
39
40
#ifndef TYPED_METHOD_BIND
41
class __UnexistingClass;
42
#define MB_T __UnexistingClass
43
#else
44
#define MB_T T
45
#endif
46
47
// no return, not const
48
#ifdef TYPED_METHOD_BIND
49
template <typename T, typename... P>
50
#else
51
template <typename... P>
52
#endif
53
class MethodBindT : public MethodBind {
54
void (MB_T::*method)(P...);
55
56
protected:
57
virtual Variant::Type _gen_argument_type(int p_arg) const override {
58
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
59
return call_get_argument_type<P...>(p_arg);
60
} else {
61
return Variant::NIL;
62
}
63
}
64
65
virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
66
PropertyInfo pi;
67
call_get_argument_type_info<P...>(p_arg, pi);
68
return pi;
69
}
70
71
public:
72
#ifdef DEBUG_ENABLED
73
virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
74
return call_get_argument_metadata<P...>(p_arg);
75
}
76
77
#endif // DEBUG_ENABLED
78
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
79
#ifdef TOOLS_ENABLED
80
ERR_FAIL_COND_V_MSG(p_object && p_object->is_extension_placeholder() && p_object->get_class_name() == get_instance_class(), Variant(), vformat("Cannot call method bind '%s' on placeholder instance.", MethodBind::get_name()));
81
#endif
82
#ifdef TYPED_METHOD_BIND
83
call_with_variant_args_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments());
84
#else
85
call_with_variant_args_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments());
86
#endif
87
return Variant();
88
}
89
90
virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
91
#ifdef TOOLS_ENABLED
92
ERR_FAIL_COND_MSG(p_object && p_object->is_extension_placeholder() && p_object->get_class_name() == get_instance_class(), vformat("Cannot call method bind '%s' on placeholder instance.", MethodBind::get_name()));
93
#endif
94
#ifdef TYPED_METHOD_BIND
95
call_with_validated_object_instance_args(static_cast<T *>(p_object), method, p_args);
96
#else
97
call_with_validated_object_instance_args(reinterpret_cast<MB_T *>(p_object), method, p_args);
98
#endif
99
}
100
101
virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
102
#ifdef TOOLS_ENABLED
103
ERR_FAIL_COND_MSG(p_object && p_object->is_extension_placeholder() && p_object->get_class_name() == get_instance_class(), vformat("Cannot call method bind '%s' on placeholder instance.", MethodBind::get_name()));
104
#endif
105
#ifdef TYPED_METHOD_BIND
106
call_with_ptr_args<T, P...>(static_cast<T *>(p_object), method, p_args);
107
#else
108
call_with_ptr_args<MB_T, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args);
109
#endif
110
}
111
112
MethodBindT(void (MB_T::*p_method)(P...)) {
113
method = p_method;
114
_generate_argument_types(sizeof...(P));
115
set_argument_count(sizeof...(P));
116
}
117
};
118
119
template <typename T, typename... P>
120
MethodBind *create_method_bind(void (T::*p_method)(P...)) {
121
#ifdef TYPED_METHOD_BIND
122
MethodBind *a = memnew((MethodBindT<T, P...>)(p_method));
123
#else
124
MethodBind *a = memnew((MethodBindT<P...>)(reinterpret_cast<void (MB_T::*)(P...)>(p_method)));
125
#endif
126
a->set_instance_class(T::get_class_static());
127
return a;
128
}
129
130
// no return, const
131
132
#ifdef TYPED_METHOD_BIND
133
template <typename T, typename... P>
134
#else
135
template <typename... P>
136
#endif
137
class MethodBindTC : public MethodBind {
138
void (MB_T::*method)(P...) const;
139
140
protected:
141
virtual Variant::Type _gen_argument_type(int p_arg) const override {
142
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
143
return call_get_argument_type<P...>(p_arg);
144
} else {
145
return Variant::NIL;
146
}
147
}
148
149
virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
150
PropertyInfo pi;
151
call_get_argument_type_info<P...>(p_arg, pi);
152
return pi;
153
}
154
155
public:
156
#ifdef DEBUG_ENABLED
157
virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
158
return call_get_argument_metadata<P...>(p_arg);
159
}
160
161
#endif // DEBUG_ENABLED
162
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
163
#ifdef TOOLS_ENABLED
164
ERR_FAIL_COND_V_MSG(p_object && p_object->is_extension_placeholder() && p_object->get_class_name() == get_instance_class(), Variant(), vformat("Cannot call method bind '%s' on placeholder instance.", MethodBind::get_name()));
165
#endif
166
#ifdef TYPED_METHOD_BIND
167
call_with_variant_argsc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments());
168
#else
169
call_with_variant_argsc_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments());
170
#endif
171
return Variant();
172
}
173
174
virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
175
#ifdef TOOLS_ENABLED
176
ERR_FAIL_COND_MSG(p_object && p_object->is_extension_placeholder() && p_object->get_class_name() == get_instance_class(), vformat("Cannot call method bind '%s' on placeholder instance.", MethodBind::get_name()));
177
#endif
178
#ifdef TYPED_METHOD_BIND
179
call_with_validated_object_instance_argsc(static_cast<T *>(p_object), method, p_args);
180
#else
181
call_with_validated_object_instance_argsc(reinterpret_cast<MB_T *>(p_object), method, p_args);
182
#endif
183
}
184
185
virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
186
#ifdef TOOLS_ENABLED
187
ERR_FAIL_COND_MSG(p_object && p_object->is_extension_placeholder() && p_object->get_class_name() == get_instance_class(), vformat("Cannot call method bind '%s' on placeholder instance.", MethodBind::get_name()));
188
#endif
189
#ifdef TYPED_METHOD_BIND
190
call_with_ptr_argsc<T, P...>(static_cast<T *>(p_object), method, p_args);
191
#else
192
call_with_ptr_argsc<MB_T, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args);
193
#endif
194
}
195
196
MethodBindTC(void (MB_T::*p_method)(P...) const) {
197
method = p_method;
198
_set_const(true);
199
_generate_argument_types(sizeof...(P));
200
set_argument_count(sizeof...(P));
201
}
202
};
203
204
template <typename T, typename... P>
205
MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
206
#ifdef TYPED_METHOD_BIND
207
MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method));
208
#else
209
MethodBind *a = memnew((MethodBindTC<P...>)(reinterpret_cast<void (MB_T::*)(P...) const>(p_method)));
210
#endif
211
a->set_instance_class(T::get_class_static());
212
return a;
213
}
214
215
// return, not const
216
217
#ifdef TYPED_METHOD_BIND
218
template <typename T, typename R, typename... P>
219
#else
220
template <typename R, typename... P>
221
#endif
222
class MethodBindTR : public MethodBind {
223
R (MB_T::*method)(P...);
224
225
protected:
226
virtual Variant::Type _gen_argument_type(int p_arg) const override {
227
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
228
return call_get_argument_type<P...>(p_arg);
229
} else {
230
return GetTypeInfo<R>::VARIANT_TYPE;
231
}
232
}
233
234
virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
235
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
236
PropertyInfo pi;
237
call_get_argument_type_info<P...>(p_arg, pi);
238
return pi;
239
} else {
240
return GetTypeInfo<R>::get_class_info();
241
}
242
}
243
244
public:
245
#ifdef DEBUG_ENABLED
246
virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
247
if (p_arg >= 0) {
248
return call_get_argument_metadata<P...>(p_arg);
249
} else {
250
return GetTypeInfo<R>::METADATA;
251
}
252
}
253
#endif // DEBUG_ENABLED
254
255
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
256
Variant ret;
257
#ifdef TOOLS_ENABLED
258
ERR_FAIL_COND_V_MSG(p_object && p_object->is_extension_placeholder() && p_object->get_class_name() == get_instance_class(), ret, vformat("Cannot call method bind '%s' on placeholder instance.", MethodBind::get_name()));
259
#endif
260
#ifdef TYPED_METHOD_BIND
261
call_with_variant_args_ret_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments());
262
#else
263
call_with_variant_args_ret_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments());
264
#endif
265
return ret;
266
}
267
268
virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
269
#ifdef TOOLS_ENABLED
270
ERR_FAIL_COND_MSG(p_object && p_object->is_extension_placeholder() && p_object->get_class_name() == get_instance_class(), vformat("Cannot call method bind '%s' on placeholder instance.", MethodBind::get_name()));
271
#endif
272
#ifdef TYPED_METHOD_BIND
273
call_with_validated_object_instance_args_ret(static_cast<T *>(p_object), method, p_args, r_ret);
274
#else
275
call_with_validated_object_instance_args_ret(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret);
276
#endif
277
}
278
279
virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
280
#ifdef TOOLS_ENABLED
281
ERR_FAIL_COND_MSG(p_object && p_object->is_extension_placeholder() && p_object->get_class_name() == get_instance_class(), vformat("Cannot call method bind '%s' on placeholder instance.", MethodBind::get_name()));
282
#endif
283
#ifdef TYPED_METHOD_BIND
284
call_with_ptr_args_ret<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret);
285
#else
286
call_with_ptr_args_ret<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret);
287
#endif
288
}
289
290
MethodBindTR(R (MB_T::*p_method)(P...)) {
291
method = p_method;
292
_set_returns(true);
293
_generate_argument_types(sizeof...(P));
294
set_argument_count(sizeof...(P));
295
}
296
};
297
298
template <typename T, typename R, typename... P>
299
MethodBind *create_method_bind(R (T::*p_method)(P...)) {
300
#ifdef TYPED_METHOD_BIND
301
MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method));
302
#else
303
MethodBind *a = memnew((MethodBindTR<R, P...>)(reinterpret_cast<R (MB_T::*)(P...)>(p_method)));
304
#endif
305
306
a->set_instance_class(T::get_class_static());
307
return a;
308
}
309
310
// return, const
311
312
#ifdef TYPED_METHOD_BIND
313
template <typename T, typename R, typename... P>
314
#else
315
template <typename R, typename... P>
316
#endif
317
class MethodBindTRC : public MethodBind {
318
R (MB_T::*method)(P...) const;
319
320
protected:
321
virtual Variant::Type _gen_argument_type(int p_arg) const override {
322
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
323
return call_get_argument_type<P...>(p_arg);
324
} else {
325
return GetTypeInfo<R>::VARIANT_TYPE;
326
}
327
}
328
329
virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
330
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
331
PropertyInfo pi;
332
call_get_argument_type_info<P...>(p_arg, pi);
333
return pi;
334
} else {
335
return GetTypeInfo<R>::get_class_info();
336
}
337
}
338
339
public:
340
#ifdef DEBUG_ENABLED
341
virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
342
if (p_arg >= 0) {
343
return call_get_argument_metadata<P...>(p_arg);
344
} else {
345
return GetTypeInfo<R>::METADATA;
346
}
347
}
348
#endif // DEBUG_ENABLED
349
350
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
351
Variant ret;
352
#ifdef TOOLS_ENABLED
353
ERR_FAIL_COND_V_MSG(p_object && p_object->is_extension_placeholder() && p_object->get_class_name() == get_instance_class(), ret, vformat("Cannot call method bind '%s' on placeholder instance.", MethodBind::get_name()));
354
#endif
355
#ifdef TYPED_METHOD_BIND
356
call_with_variant_args_retc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments());
357
#else
358
call_with_variant_args_retc_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments());
359
#endif
360
return ret;
361
}
362
363
virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
364
#ifdef TOOLS_ENABLED
365
ERR_FAIL_COND_MSG(p_object && p_object->is_extension_placeholder() && p_object->get_class_name() == get_instance_class(), vformat("Cannot call method bind '%s' on placeholder instance.", MethodBind::get_name()));
366
#endif
367
#ifdef TYPED_METHOD_BIND
368
call_with_validated_object_instance_args_retc(static_cast<T *>(p_object), method, p_args, r_ret);
369
#else
370
call_with_validated_object_instance_args_retc(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret);
371
#endif
372
}
373
374
virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
375
#ifdef TOOLS_ENABLED
376
ERR_FAIL_COND_MSG(p_object && p_object->is_extension_placeholder() && p_object->get_class_name() == get_instance_class(), vformat("Cannot call method bind '%s' on placeholder instance.", MethodBind::get_name()));
377
#endif
378
#ifdef TYPED_METHOD_BIND
379
call_with_ptr_args_retc<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret);
380
#else
381
call_with_ptr_args_retc<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret);
382
#endif
383
}
384
385
MethodBindTRC(R (MB_T::*p_method)(P...) const) {
386
method = p_method;
387
_set_returns(true);
388
_set_const(true);
389
_generate_argument_types(sizeof...(P));
390
set_argument_count(sizeof...(P));
391
}
392
};
393
394
template <typename T, typename R, typename... P>
395
MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
396
#ifdef TYPED_METHOD_BIND
397
MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method));
398
#else
399
MethodBind *a = memnew((MethodBindTRC<R, P...>)(reinterpret_cast<R (MB_T::*)(P...) const>(p_method)));
400
#endif
401
a->set_instance_class(T::get_class_static());
402
return a;
403
}
404
405
/* STATIC BINDS */
406
407
// no return
408
409
template <typename... P>
410
class MethodBindTS : public MethodBind {
411
void (*function)(P...);
412
413
protected:
414
virtual Variant::Type _gen_argument_type(int p_arg) const override {
415
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
416
return call_get_argument_type<P...>(p_arg);
417
} else {
418
return Variant::NIL;
419
}
420
}
421
422
virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
423
PropertyInfo pi;
424
call_get_argument_type_info<P...>(p_arg, pi);
425
return pi;
426
}
427
428
public:
429
#ifdef DEBUG_ENABLED
430
virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
431
return call_get_argument_metadata<P...>(p_arg);
432
}
433
434
#endif // DEBUG_ENABLED
435
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
436
(void)p_object; // unused
437
call_with_variant_args_static_dv(function, p_args, p_arg_count, r_error, get_default_arguments());
438
return Variant();
439
}
440
441
virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
442
call_with_validated_variant_args_static_method(function, p_args);
443
}
444
445
virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
446
(void)p_object;
447
(void)r_ret;
448
call_with_ptr_args_static_method(function, p_args);
449
}
450
451
MethodBindTS(void (*p_function)(P...)) {
452
function = p_function;
453
_generate_argument_types(sizeof...(P));
454
set_argument_count(sizeof...(P));
455
_set_static(true);
456
}
457
};
458
459
template <typename... P>
460
MethodBind *create_static_method_bind(void (*p_method)(P...)) {
461
MethodBind *a = memnew((MethodBindTS<P...>)(p_method));
462
return a;
463
}
464
465
// return
466
467
template <typename R, typename... P>
468
class MethodBindTRS : public MethodBind {
469
R (*function)(P...);
470
471
protected:
472
virtual Variant::Type _gen_argument_type(int p_arg) const override {
473
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
474
return call_get_argument_type<P...>(p_arg);
475
} else {
476
return GetTypeInfo<R>::VARIANT_TYPE;
477
}
478
}
479
480
virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
481
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
482
PropertyInfo pi;
483
call_get_argument_type_info<P...>(p_arg, pi);
484
return pi;
485
} else {
486
return GetTypeInfo<R>::get_class_info();
487
}
488
}
489
490
public:
491
#ifdef DEBUG_ENABLED
492
virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
493
if (p_arg >= 0) {
494
return call_get_argument_metadata<P...>(p_arg);
495
} else {
496
return GetTypeInfo<R>::METADATA;
497
}
498
}
499
500
#endif // DEBUG_ENABLED
501
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
502
Variant ret;
503
call_with_variant_args_static_ret_dv(function, p_args, p_arg_count, ret, r_error, get_default_arguments());
504
return ret;
505
}
506
507
virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
508
call_with_validated_variant_args_static_method_ret(function, p_args, r_ret);
509
}
510
511
virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
512
(void)p_object;
513
call_with_ptr_args_static_method_ret(function, p_args, r_ret);
514
}
515
516
MethodBindTRS(R (*p_function)(P...)) {
517
function = p_function;
518
_generate_argument_types(sizeof...(P));
519
set_argument_count(sizeof...(P));
520
_set_static(true);
521
_set_returns(true);
522
}
523
};
524
525
template <typename R, typename... P>
526
MethodBind *create_static_method_bind(R (*p_method)(P...)) {
527
MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method));
528
return a;
529
}
530
531