Skip to content

Commit 6f0d0a6

Browse files
Bind CXX callable objects as methods
Signed-off-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
1 parent 713481f commit 6f0d0a6

File tree

2 files changed

+539
-0
lines changed

2 files changed

+539
-0
lines changed

include/godot_cpp/core/binder_common.hpp

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <godot_cpp/core/type_info.hpp>
3838

3939
#include <array>
40+
#include <functional>
4041

4142
namespace godot {
4243

@@ -208,6 +209,26 @@ void call_with_ptr_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const,
208209
PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
209210
}
210211

212+
template <typename T, typename... P, size_t... Is>
213+
void call_with_ptr_args_helper(T *p_instance, std::function<void (T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) {
214+
p_method(*p_instance, PtrToArg<P>::convert(p_args[Is])...);
215+
}
216+
217+
template <typename T, typename... P, size_t... Is>
218+
void call_with_ptr_argsc_helper(T *p_instance, std::function<void (const T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) {
219+
p_method(*p_instance, PtrToArg<P>::convert(p_args[Is])...);
220+
}
221+
222+
template <typename T, typename R, typename... P, size_t... Is>
223+
void call_with_ptr_args_ret_helper(T *p_instance, std::function<R (T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
224+
PtrToArg<R>::encode(p_method(*p_instance, PtrToArg<P>::convert(p_args[Is])...), r_ret);
225+
}
226+
227+
template <typename T, typename R, typename... P, size_t... Is>
228+
void call_with_ptr_args_retc_helper(T *p_instance, std::function<R (const T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
229+
PtrToArg<R>::encode(p_method(*p_instance, PtrToArg<P>::convert(p_args[Is])...), r_ret);
230+
}
231+
211232
template <typename T, typename... P>
212233
void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, void * /*ret*/) {
213234
call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
@@ -228,6 +249,26 @@ void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...) const, const GDExt
228249
call_with_ptr_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
229250
}
230251

252+
template <typename T, typename... P>
253+
void call_with_ptr_args(T *p_instance, std::function<void (T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, void * /*ret*/) {
254+
call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
255+
}
256+
257+
template <typename T, typename... P>
258+
void call_with_ptr_args(T *p_instance, std::function<void (const T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, void * /*ret*/) {
259+
call_with_ptr_argsc_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
260+
}
261+
262+
template <typename T, typename R, typename... P>
263+
void call_with_ptr_args(T *p_instance, std::function<R (T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, void *r_ret) {
264+
call_with_ptr_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
265+
}
266+
267+
template <typename T, typename R, typename... P>
268+
void call_with_ptr_args(T *p_instance, std::function<R (const T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, void *r_ret) {
269+
call_with_ptr_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
270+
}
271+
231272
template <typename T, typename... P, size_t... Is>
232273
void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
233274
r_error.error = GDEXTENSION_CALL_OK;
@@ -470,6 +511,248 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const,
470511
call_with_variant_args_retc_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
471512
}
472513

514+
template <typename T, typename... P, size_t... Is>
515+
void call_with_variant_args_helper(T *p_instance, std::function<void (const T &, P...)> &p_method, const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
516+
r_error.error = GDEXTENSION_CALL_OK;
517+
518+
#ifdef DEBUG_METHODS_ENABLED
519+
(p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
520+
#else
521+
(p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
522+
#endif
523+
(void)(p_args); // Avoid warning.
524+
}
525+
526+
template <typename T, typename... P, size_t... Is>
527+
void call_with_variant_argsc_helper(T *p_instance, std::function<void (const T &, P...)> &p_method, const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
528+
r_error.error = GDEXTENSION_CALL_OK;
529+
530+
#ifdef DEBUG_METHODS_ENABLED
531+
(p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
532+
#else
533+
(p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
534+
#endif
535+
(void)(p_args); // Avoid warning.
536+
}
537+
538+
template <typename T, typename R, typename... P, size_t... Is>
539+
void call_with_variant_args_ret_helper(T *p_instance, std::function<R (T &, P...)> &p_method, const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
540+
r_error.error = GDEXTENSION_CALL_OK;
541+
542+
#ifdef DEBUG_METHODS_ENABLED
543+
r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
544+
#else
545+
r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
546+
#endif
547+
(void)p_args; // Avoid warning.
548+
}
549+
550+
template <typename T, typename R, typename... P, size_t... Is>
551+
void call_with_variant_args_retc_helper(T *p_instance, std::function<R (const T &, P...)> &p_method, const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
552+
r_error.error = GDEXTENSION_CALL_OK;
553+
554+
#ifdef DEBUG_METHODS_ENABLED
555+
r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
556+
#else
557+
r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
558+
#endif
559+
(void)p_args; // Avoid warning.
560+
}
561+
562+
template <typename T, typename... P>
563+
void call_with_variant_args(T *p_instance, std::function<void (T &, P...)> &p_method, const Variant **p_args, int p_argcount, GDExtensionCallError &r_error) {
564+
#ifdef DEBUG_ENABLED
565+
if ((size_t)p_argcount > sizeof...(P)) {
566+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
567+
r_error.expected = (int32_t)sizeof...(P);
568+
return;
569+
}
570+
571+
if ((size_t)p_argcount < sizeof...(P)) {
572+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
573+
r_error.expected = (int32_t)sizeof...(P);
574+
return;
575+
}
576+
#endif
577+
call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
578+
}
579+
580+
template <typename T, typename R, typename... P>
581+
void call_with_variant_args_ret(T *p_instance, std::function<R (T &, P...)> &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
582+
#ifdef DEBUG_ENABLED
583+
if ((size_t)p_argcount > sizeof...(P)) {
584+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
585+
r_error.expected = (int32_t)sizeof...(P);
586+
return;
587+
}
588+
589+
if ((size_t)p_argcount < sizeof...(P)) {
590+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
591+
r_error.expected = (int32_t)sizeof...(P);
592+
return;
593+
}
594+
#endif
595+
call_with_variant_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
596+
}
597+
598+
template <typename T, typename R, typename... P>
599+
void call_with_variant_args_retc(T *p_instance, std::function<R (const T &, P...)> &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
600+
#ifdef DEBUG_ENABLED
601+
if ((size_t)p_argcount > sizeof...(P)) {
602+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
603+
r_error.expected = (int32_t)sizeof...(P);
604+
return;
605+
}
606+
607+
if ((size_t)p_argcount < sizeof...(P)) {
608+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
609+
r_error.expected = (int32_t)sizeof...(P);
610+
return;
611+
}
612+
#endif
613+
call_with_variant_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
614+
}
615+
616+
template <typename T, typename... P>
617+
void call_with_variant_args_dv(T *p_instance, std::function<void (T &, P...)> &p_method, const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const LocalVector<Variant> &default_values) {
618+
#ifdef DEBUG_ENABLED
619+
if ((size_t)p_argcount > sizeof...(P)) {
620+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
621+
r_error.expected = (int32_t)sizeof...(P);
622+
return;
623+
}
624+
#endif
625+
626+
int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
627+
628+
int32_t dvs = (int32_t)default_values.size();
629+
#ifdef DEBUG_ENABLED
630+
if (missing > dvs) {
631+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
632+
r_error.expected = (int32_t)sizeof...(P);
633+
return;
634+
}
635+
#endif
636+
637+
Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
638+
std::array<const Variant *, sizeof...(P)> argsp;
639+
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
640+
if (i < p_argcount) {
641+
args[i] = Variant(p_args[i]);
642+
} else {
643+
args[i] = default_values[i - p_argcount + (dvs - missing)];
644+
}
645+
argsp[i] = &args[i];
646+
}
647+
648+
call_with_variant_args_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
649+
}
650+
651+
template <typename T, typename... P>
652+
void call_with_variant_argsc_dv(T *p_instance, std::function<void (const T &, P...)> &p_method, const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const LocalVector<Variant> &default_values) {
653+
#ifdef DEBUG_ENABLED
654+
if ((size_t)p_argcount > sizeof...(P)) {
655+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
656+
r_error.expected = (int32_t)sizeof...(P);
657+
return;
658+
}
659+
#endif
660+
661+
int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
662+
663+
int32_t dvs = (int32_t)default_values.size();
664+
#ifdef DEBUG_ENABLED
665+
if (missing > dvs) {
666+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
667+
r_error.expected = (int32_t)sizeof...(P);
668+
return;
669+
}
670+
#endif
671+
672+
Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
673+
std::array<const Variant *, sizeof...(P)> argsp;
674+
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
675+
if (i < p_argcount) {
676+
args[i] = Variant(p_args[i]);
677+
} else {
678+
args[i] = default_values[i - p_argcount + (dvs - missing)];
679+
}
680+
argsp[i] = &args[i];
681+
}
682+
683+
call_with_variant_argsc_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
684+
}
685+
686+
template <typename T, typename R, typename... P>
687+
void call_with_variant_args_ret_dv(T *p_instance, std::function<R (T &, P...)> &p_method, const GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const LocalVector<Variant> &default_values) {
688+
#ifdef DEBUG_ENABLED
689+
if ((size_t)p_argcount > sizeof...(P)) {
690+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
691+
r_error.expected = (int32_t)sizeof...(P);
692+
return;
693+
}
694+
#endif
695+
696+
int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
697+
698+
int32_t dvs = (int32_t)default_values.size();
699+
#ifdef DEBUG_ENABLED
700+
if (missing > dvs) {
701+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
702+
r_error.expected = (int32_t)sizeof...(P);
703+
return;
704+
}
705+
#endif
706+
707+
Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
708+
std::array<const Variant *, sizeof...(P)> argsp;
709+
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
710+
if (i < p_argcount) {
711+
args[i] = Variant(p_args[i]);
712+
} else {
713+
args[i] = default_values[i - p_argcount + (dvs - missing)];
714+
}
715+
argsp[i] = &args[i];
716+
}
717+
718+
call_with_variant_args_ret_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
719+
}
720+
721+
template <typename T, typename R, typename... P>
722+
void call_with_variant_args_retc_dv(T *p_instance, std::function<R (const T &, P...)> &p_method, const GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const LocalVector<Variant> &default_values) {
723+
#ifdef DEBUG_ENABLED
724+
if ((size_t)p_argcount > sizeof...(P)) {
725+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
726+
r_error.expected = (int32_t)sizeof...(P);
727+
return;
728+
}
729+
#endif
730+
731+
int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
732+
733+
int32_t dvs = (int32_t)default_values.size();
734+
#ifdef DEBUG_ENABLED
735+
if (missing > dvs) {
736+
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
737+
r_error.expected = (int32_t)sizeof...(P);
738+
return;
739+
}
740+
#endif
741+
742+
Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
743+
std::array<const Variant *, sizeof...(P)> argsp;
744+
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
745+
if (i < p_argcount) {
746+
args[i] = Variant(p_args[i]);
747+
} else {
748+
args[i] = default_values[i - p_argcount + (dvs - missing)];
749+
}
750+
argsp[i] = &args[i];
751+
}
752+
753+
call_with_variant_args_retc_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
754+
}
755+
473756
// GCC raises "parameter 'p_args' set but not used" when P = {},
474757
// it's not clever enough to treat other P values as making this branch valid.
475758
#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)

0 commit comments

Comments
 (0)