Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
283 changes: 283 additions & 0 deletions include/godot_cpp/core/binder_common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <godot_cpp/core/type_info.hpp>

#include <array>
#include <functional>

namespace godot {

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

template <typename T, typename... P, size_t... Is>
void call_with_ptr_args_helper(T *p_instance, const std::function<void(T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) {
p_method(*p_instance, PtrToArg<P>::convert(p_args[Is])...);
}

template <typename T, typename... P, size_t... Is>
void call_with_ptr_argsc_helper(T *p_instance, const std::function<void(const T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) {
p_method(*p_instance, PtrToArg<P>::convert(p_args[Is])...);
}

template <typename T, typename R, typename... P, size_t... Is>
void call_with_ptr_args_ret_helper(T *p_instance, const std::function<R(T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
PtrToArg<R>::encode(p_method(*p_instance, PtrToArg<P>::convert(p_args[Is])...), r_ret);
}

template <typename T, typename R, typename... P, size_t... Is>
void call_with_ptr_args_retc_helper(T *p_instance, const std::function<R(const T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
PtrToArg<R>::encode(p_method(*p_instance, PtrToArg<P>::convert(p_args[Is])...), r_ret);
}

template <typename T, typename... P>
void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, void * /*ret*/) {
call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
Expand All @@ -228,6 +249,26 @@ void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...) const, const GDExt
call_with_ptr_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}

template <typename T, typename... P>
void call_with_ptr_args(T *p_instance, const std::function<void(T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, void * /*ret*/) {
call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}

template <typename T, typename... P>
void call_with_ptr_args(T *p_instance, const std::function<void(const T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, void * /*ret*/) {
call_with_ptr_argsc_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}

template <typename T, typename R, typename... P>
void call_with_ptr_args(T *p_instance, const std::function<R(T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, void *r_ret) {
call_with_ptr_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}

template <typename T, typename R, typename... P>
void call_with_ptr_args(T *p_instance, const std::function<R(const T &, P...)> &p_method, const GDExtensionConstTypePtr *p_args, void *r_ret) {
call_with_ptr_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}

template <typename T, typename... P, size_t... Is>
void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDEXTENSION_CALL_OK;
Expand Down Expand Up @@ -470,6 +511,248 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const,
call_with_variant_args_retc_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}

template <typename T, typename... P, size_t... Is>
void call_with_variant_args_helper(T *p_instance, const std::function<void(const T &, P...)> &p_method, const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDEXTENSION_CALL_OK;

#ifdef DEBUG_METHODS_ENABLED
p_method(*p_instance, VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
#else
p_method(*p_instance, VariantCaster<P>::cast(*p_args[Is])...);
#endif
(void)(p_args); // Avoid warning.
}

template <typename T, typename... P, size_t... Is>
void call_with_variant_argsc_helper(T *p_instance, const std::function<void(const T &, P...)> &p_method, const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDEXTENSION_CALL_OK;

#ifdef DEBUG_METHODS_ENABLED
p_method(*p_instance, VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
#else
p_method(*p_instance, VariantCaster<P>::cast(*p_args[Is])...);
#endif
(void)(p_args); // Avoid warning.
}

template <typename T, typename R, typename... P, size_t... Is>
void call_with_variant_args_ret_helper(T *p_instance, const std::function<R(T &, P...)> &p_method, const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDEXTENSION_CALL_OK;

#ifdef DEBUG_METHODS_ENABLED
r_ret = p_method(*p_instance, VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
#else
r_ret = p_method(*p_instance, VariantCaster<P>::cast(*p_args[Is])...);
#endif
(void)p_args; // Avoid warning.
}

template <typename T, typename R, typename... P, size_t... Is>
void call_with_variant_args_retc_helper(T *p_instance, const std::function<R(const T &, P...)> &p_method, const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDEXTENSION_CALL_OK;

#ifdef DEBUG_METHODS_ENABLED
r_ret = p_method(*p_instance, VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
#else
r_ret = p_method(*p_instance, VariantCaster<P>::cast(*p_args[Is])...);
#endif
(void)p_args; // Avoid warning.
}

template <typename T, typename... P>
void call_with_variant_args(T *p_instance, const std::function<void(T &, P...)> &p_method, const Variant **p_args, int p_argcount, GDExtensionCallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}

if ((size_t)p_argcount < sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
}

template <typename T, typename R, typename... P>
void call_with_variant_args_ret(T *p_instance, const std::function<R(T &, P...)> &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}

if ((size_t)p_argcount < sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
call_with_variant_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}

template <typename T, typename R, typename... P>
void call_with_variant_args_retc(T *p_instance, const std::function<R(const T &, P...)> &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}

if ((size_t)p_argcount < sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
call_with_variant_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}

template <typename T, typename... P>
void call_with_variant_args_dv(T *p_instance, const std::function<void(T &, P...)> &p_method, const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const LocalVector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif

int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;

int32_t dvs = (int32_t)default_values.size();
#ifdef DEBUG_ENABLED
if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif

Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
std::array<const Variant *, sizeof...(P)> argsp;
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
if (i < p_argcount) {
args[i] = Variant(p_args[i]);
} else {
args[i] = default_values[i - p_argcount + (dvs - missing)];
}
argsp[i] = &args[i];
}

call_with_variant_args_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
}

template <typename T, typename... P>
void call_with_variant_argsc_dv(T *p_instance, const std::function<void(const T &, P...)> &p_method, const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const LocalVector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif

int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;

int32_t dvs = (int32_t)default_values.size();
#ifdef DEBUG_ENABLED
if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif

Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
std::array<const Variant *, sizeof...(P)> argsp;
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
if (i < p_argcount) {
args[i] = Variant(p_args[i]);
} else {
args[i] = default_values[i - p_argcount + (dvs - missing)];
}
argsp[i] = &args[i];
}

call_with_variant_argsc_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
}

template <typename T, typename R, typename... P>
void call_with_variant_args_ret_dv(T *p_instance, const 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) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif

int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;

int32_t dvs = (int32_t)default_values.size();
#ifdef DEBUG_ENABLED
if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif

Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
std::array<const Variant *, sizeof...(P)> argsp;
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
if (i < p_argcount) {
args[i] = Variant(p_args[i]);
} else {
args[i] = default_values[i - p_argcount + (dvs - missing)];
}
argsp[i] = &args[i];
}

call_with_variant_args_ret_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}

template <typename T, typename R, typename... P>
void call_with_variant_args_retc_dv(T *p_instance, const 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) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif

int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;

int32_t dvs = (int32_t)default_values.size();
#ifdef DEBUG_ENABLED
if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif

Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
std::array<const Variant *, sizeof...(P)> argsp;
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
if (i < p_argcount) {
args[i] = Variant(p_args[i]);
} else {
args[i] = default_values[i - p_argcount + (dvs - missing)];
}
argsp[i] = &args[i];
}

call_with_variant_args_retc_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}

// GCC raises "parameter 'p_args' set but not used" when P = {},
// it's not clever enough to treat other P values as making this branch valid.
#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
Expand Down
Loading
Loading