binder_common.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*************************************************************************/
  2. /* binder_common.hpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
  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. #ifndef GODOT_BINDER_COMMON_HPP
  31. #define GODOT_BINDER_COMMON_HPP
  32. #include <godot/gdextension_interface.h>
  33. #include <godot_cpp/core/method_ptrcall.hpp>
  34. #include <godot_cpp/core/type_info.hpp>
  35. #include <array>
  36. #include <vector>
  37. namespace godot {
  38. #define VARIANT_ENUM_CAST(m_class, m_enum) \
  39. namespace godot { \
  40. MAKE_ENUM_TYPE_INFO(m_class, m_enum) \
  41. template <> \
  42. struct VariantCaster<m_class::m_enum> { \
  43. static _FORCE_INLINE_ m_class::m_enum cast(const Variant &p_variant) { \
  44. return (m_class::m_enum)p_variant.operator int64_t(); \
  45. } \
  46. }; \
  47. template <> \
  48. struct PtrToArg<m_class::m_enum> { \
  49. _FORCE_INLINE_ static m_class::m_enum convert(const void *p_ptr) { \
  50. return m_class::m_enum(*reinterpret_cast<const int64_t *>(p_ptr)); \
  51. } \
  52. typedef int64_t EncodeT; \
  53. _FORCE_INLINE_ static void encode(m_class::m_enum p_val, void *p_ptr) { \
  54. *reinterpret_cast<int64_t *>(p_ptr) = p_val; \
  55. } \
  56. }; \
  57. }
  58. #define VARIANT_BITFIELD_CAST(m_class, m_enum) \
  59. namespace godot { \
  60. MAKE_BITFIELD_TYPE_INFO(m_class, m_enum) \
  61. template <> \
  62. struct VariantCaster<BitField<m_class::m_enum>> { \
  63. static _FORCE_INLINE_ BitField<m_class::m_enum> cast(const Variant &p_variant) { \
  64. return BitField<m_class::m_enum>(p_variant.operator int64_t()); \
  65. } \
  66. }; \
  67. template <> \
  68. struct PtrToArg<BitField<m_class::m_enum>> { \
  69. _FORCE_INLINE_ static BitField<m_class::m_enum> convert(const void *p_ptr) { \
  70. return BitField<m_class::m_enum>(*reinterpret_cast<const int64_t *>(p_ptr)); \
  71. } \
  72. typedef int64_t EncodeT; \
  73. _FORCE_INLINE_ static void encode(BitField<m_class::m_enum> p_val, void *p_ptr) { \
  74. *reinterpret_cast<int64_t *>(p_ptr) = p_val; \
  75. } \
  76. }; \
  77. }
  78. template <class T>
  79. struct VariantCaster {
  80. static _FORCE_INLINE_ T cast(const Variant &p_variant) {
  81. return p_variant;
  82. }
  83. };
  84. template <class T>
  85. struct VariantCaster<T &> {
  86. static _FORCE_INLINE_ T cast(const Variant &p_variant) {
  87. return p_variant;
  88. }
  89. };
  90. template <class T>
  91. struct VariantCaster<const T &> {
  92. static _FORCE_INLINE_ T cast(const Variant &p_variant) {
  93. return p_variant;
  94. }
  95. };
  96. template <typename T>
  97. struct VariantObjectClassChecker {
  98. static _FORCE_INLINE_ bool check(const Variant &p_variant) {
  99. return true;
  100. }
  101. };
  102. template <typename T>
  103. class Ref;
  104. template <typename T>
  105. struct VariantObjectClassChecker<const Ref<T> &> {
  106. static _FORCE_INLINE_ bool check(const Variant &p_variant) {
  107. Object *obj = p_variant;
  108. const Ref<T> node = p_variant;
  109. return node.ptr() || !obj;
  110. }
  111. };
  112. template <class T>
  113. struct VariantCasterAndValidate {
  114. static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
  115. GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
  116. if (!internal::gde_interface->variant_can_convert_strict(static_cast<GDExtensionVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
  117. !VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
  118. r_error.error = GDEXTENSION_CALL_ERROR_INVALID_ARGUMENT;
  119. r_error.argument = p_arg_idx;
  120. r_error.expected = argtype;
  121. }
  122. return VariantCaster<T>::cast(*p_args[p_arg_idx]);
  123. }
  124. };
  125. template <class T>
  126. struct VariantCasterAndValidate<T &> {
  127. static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
  128. GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
  129. if (!internal::gde_interface->variant_can_convert_strict(static_cast<GDExtensionVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
  130. !VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
  131. r_error.error = GDEXTENSION_CALL_ERROR_INVALID_ARGUMENT;
  132. r_error.argument = p_arg_idx;
  133. r_error.expected = argtype;
  134. }
  135. return VariantCaster<T>::cast(*p_args[p_arg_idx]);
  136. }
  137. };
  138. template <class T>
  139. struct VariantCasterAndValidate<const T &> {
  140. static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
  141. GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
  142. if (!internal::gde_interface->variant_can_convert_strict(static_cast<GDExtensionVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
  143. !VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
  144. r_error.error = GDEXTENSION_CALL_ERROR_INVALID_ARGUMENT;
  145. r_error.argument = p_arg_idx;
  146. r_error.expected = argtype;
  147. }
  148. return VariantCaster<T>::cast(*p_args[p_arg_idx]);
  149. }
  150. };
  151. template <class T, class... P, size_t... Is>
  152. void call_with_ptr_args_helper(T *p_instance, void (T::*p_method)(P...), GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) {
  153. (p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...);
  154. }
  155. template <class T, class... P, size_t... Is>
  156. void call_with_ptr_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) {
  157. (p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...);
  158. }
  159. template <class T, class R, class... P, size_t... Is>
  160. void call_with_ptr_args_ret_helper(T *p_instance, R (T::*p_method)(P...), GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
  161. PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
  162. }
  163. template <class T, class R, class... P, size_t... Is>
  164. void call_with_ptr_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
  165. PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
  166. }
  167. template <class T, class... P>
  168. void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), GDExtensionConstTypePtr *p_args, void * /*ret*/) {
  169. call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
  170. }
  171. template <class T, class... P>
  172. void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...) const, GDExtensionConstTypePtr *p_args, void * /*ret*/) {
  173. call_with_ptr_argsc_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
  174. }
  175. template <class T, class R, class... P>
  176. void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...), GDExtensionConstTypePtr *p_args, void *r_ret) {
  177. call_with_ptr_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
  178. }
  179. template <class T, class R, class... P>
  180. void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...) const, GDExtensionConstTypePtr *p_args, void *r_ret) {
  181. call_with_ptr_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
  182. }
  183. template <class T, class... P, size_t... Is>
  184. void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
  185. r_error.error = GDEXTENSION_CALL_OK;
  186. #ifdef DEBUG_METHODS_ENABLED
  187. (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
  188. #else
  189. (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
  190. #endif
  191. (void)(p_args); // Avoid warning.
  192. }
  193. template <class T, class... P, size_t... Is>
  194. void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
  195. r_error.error = GDEXTENSION_CALL_OK;
  196. #ifdef DEBUG_METHODS_ENABLED
  197. (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
  198. #else
  199. (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
  200. #endif
  201. (void)(p_args); // Avoid warning.
  202. }
  203. template <class T, class R, class... P, size_t... Is>
  204. void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
  205. r_error.error = GDEXTENSION_CALL_OK;
  206. #ifdef DEBUG_METHODS_ENABLED
  207. r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
  208. #else
  209. r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
  210. #endif
  211. }
  212. template <class T, class R, class... P, size_t... Is>
  213. void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
  214. r_error.error = GDEXTENSION_CALL_OK;
  215. #ifdef DEBUG_METHODS_ENABLED
  216. r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
  217. #else
  218. r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
  219. #endif
  220. (void)p_args;
  221. }
  222. template <class T, class... P>
  223. void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
  224. #ifdef DEBUG_ENABLED
  225. if ((size_t)p_argcount > sizeof...(P)) {
  226. r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
  227. r_error.argument = (int32_t)sizeof...(P);
  228. return;
  229. }
  230. #endif
  231. int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
  232. int32_t dvs = (int32_t)default_values.size();
  233. #ifdef DEBUG_ENABLED
  234. if (missing > dvs) {
  235. r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
  236. r_error.argument = (int32_t)sizeof...(P);
  237. return;
  238. }
  239. #endif
  240. Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
  241. std::array<const Variant *, sizeof...(P)> argsp;
  242. for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
  243. if (i < p_argcount) {
  244. args[i] = Variant(p_args[i]);
  245. } else {
  246. args[i] = default_values[i - p_argcount + (dvs - missing)];
  247. }
  248. argsp[i] = &args[i];
  249. }
  250. call_with_variant_args_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
  251. }
  252. template <class T, class... P>
  253. void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
  254. #ifdef DEBUG_ENABLED
  255. if ((size_t)p_argcount > sizeof...(P)) {
  256. r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
  257. r_error.argument = (int32_t)sizeof...(P);
  258. return;
  259. }
  260. #endif
  261. int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
  262. int32_t dvs = (int32_t)default_values.size();
  263. #ifdef DEBUG_ENABLED
  264. if (missing > dvs) {
  265. r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
  266. r_error.argument = (int32_t)sizeof...(P);
  267. return;
  268. }
  269. #endif
  270. Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
  271. std::array<const Variant *, sizeof...(P)> argsp;
  272. for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
  273. if (i < p_argcount) {
  274. args[i] = Variant(p_args[i]);
  275. } else {
  276. args[i] = default_values[i - p_argcount + (dvs - missing)];
  277. }
  278. argsp[i] = &args[i];
  279. }
  280. call_with_variant_argsc_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
  281. }
  282. template <class T, class R, class... P>
  283. void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
  284. #ifdef DEBUG_ENABLED
  285. if ((size_t)p_argcount > sizeof...(P)) {
  286. r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
  287. r_error.argument = (int32_t)sizeof...(P);
  288. return;
  289. }
  290. #endif
  291. int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
  292. int32_t dvs = (int32_t)default_values.size();
  293. #ifdef DEBUG_ENABLED
  294. if (missing > dvs) {
  295. r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
  296. r_error.argument = (int32_t)sizeof...(P);
  297. return;
  298. }
  299. #endif
  300. Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
  301. std::array<const Variant *, sizeof...(P)> argsp;
  302. for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
  303. if (i < p_argcount) {
  304. args[i] = Variant(p_args[i]);
  305. } else {
  306. args[i] = default_values[i - p_argcount + (dvs - missing)];
  307. }
  308. argsp[i] = &args[i];
  309. }
  310. call_with_variant_args_ret_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
  311. }
  312. template <class T, class R, class... P>
  313. void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
  314. #ifdef DEBUG_ENABLED
  315. if ((size_t)p_argcount > sizeof...(P)) {
  316. r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
  317. r_error.argument = (int32_t)sizeof...(P);
  318. return;
  319. }
  320. #endif
  321. int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
  322. int32_t dvs = (int32_t)default_values.size();
  323. #ifdef DEBUG_ENABLED
  324. if (missing > dvs) {
  325. r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
  326. r_error.argument = (int32_t)sizeof...(P);
  327. return;
  328. }
  329. #endif
  330. Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
  331. std::array<const Variant *, sizeof...(P)> argsp;
  332. for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
  333. if (i < p_argcount) {
  334. args[i] = Variant(p_args[i]);
  335. } else {
  336. args[i] = default_values[i - p_argcount + (dvs - missing)];
  337. }
  338. argsp[i] = &args[i];
  339. }
  340. call_with_variant_args_retc_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
  341. }
  342. // GCC raises "parameter 'p_args' set but not used" when P = {},
  343. // it's not clever enough to treat other P values as making this branch valid.
  344. #if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
  345. #pragma GCC diagnostic push
  346. #pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
  347. #endif
  348. template <class Q>
  349. void call_get_argument_type_helper(int p_arg, int &index, GDExtensionVariantType &type) {
  350. if (p_arg == index) {
  351. type = GDExtensionVariantType(GetTypeInfo<Q>::VARIANT_TYPE);
  352. }
  353. index++;
  354. }
  355. template <class... P>
  356. GDExtensionVariantType call_get_argument_type(int p_arg) {
  357. GDExtensionVariantType type = GDEXTENSION_VARIANT_TYPE_NIL;
  358. int index = 0;
  359. // I think rocket science is simpler than modern C++.
  360. using expand_type = int[];
  361. expand_type a{ 0, (call_get_argument_type_helper<P>(p_arg, index, type), 0)... };
  362. (void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning.
  363. (void)index; // Suppress GCC warning.
  364. return type;
  365. }
  366. template <class Q>
  367. void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &info) {
  368. if (p_arg == index) {
  369. info = GetTypeInfo<Q>::get_class_info();
  370. }
  371. index++;
  372. }
  373. template <class... P>
  374. void call_get_argument_type_info(int p_arg, PropertyInfo &info) {
  375. int index = 0;
  376. // I think rocket science is simpler than modern C++.
  377. using expand_type = int[];
  378. expand_type a{ 0, (call_get_argument_type_info_helper<P>(p_arg, index, info), 0)... };
  379. (void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning.
  380. (void)index; // Suppress GCC warning.
  381. }
  382. template <class Q>
  383. void call_get_argument_metadata_helper(int p_arg, int &index, GDExtensionClassMethodArgumentMetadata &md) {
  384. if (p_arg == index) {
  385. md = GetTypeInfo<Q>::METADATA;
  386. }
  387. index++;
  388. }
  389. template <class... P>
  390. GDExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_arg) {
  391. GDExtensionClassMethodArgumentMetadata md = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
  392. int index = 0;
  393. // I think rocket science is simpler than modern C++.
  394. using expand_type = int[];
  395. expand_type a{ 0, (call_get_argument_metadata_helper<P>(p_arg, index, md), 0)... };
  396. (void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning.
  397. (void)index;
  398. return md;
  399. }
  400. template <class... P, size_t... Is>
  401. void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
  402. r_error.error = GDEXTENSION_CALL_OK;
  403. #ifdef DEBUG_METHODS_ENABLED
  404. (p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
  405. #else
  406. (p_method)(VariantCaster<P>::cast(*p_args[Is])...);
  407. #endif
  408. }
  409. template <class... P>
  410. void call_with_variant_args_static_dv(void (*p_method)(P...), GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
  411. #ifdef DEBUG_ENABLED
  412. if ((size_t)p_argcount > sizeof...(P)) {
  413. r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
  414. r_error.argument = sizeof...(P);
  415. return;
  416. }
  417. #endif
  418. int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
  419. int32_t dvs = default_values.size();
  420. #ifdef DEBUG_ENABLED
  421. if (missing > dvs) {
  422. r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
  423. r_error.argument = sizeof...(P);
  424. return;
  425. }
  426. #endif
  427. Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
  428. std::array<const Variant *, sizeof...(P)> argsp;
  429. for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
  430. if (i < p_argcount) {
  431. args[i] = Variant(p_args[i]);
  432. } else {
  433. args[i] = default_values[i - p_argcount + (dvs - missing)];
  434. }
  435. argsp[i] = &args[i];
  436. }
  437. call_with_variant_args_static(p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
  438. }
  439. template <class... P, size_t... Is>
  440. void call_with_ptr_args_static_method_helper(void (*p_method)(P...), GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) {
  441. p_method(PtrToArg<P>::convert(p_args[Is])...);
  442. }
  443. template <class... P>
  444. void call_with_ptr_args_static_method(void (*p_method)(P...), GDExtensionConstTypePtr *p_args) {
  445. call_with_ptr_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
  446. }
  447. template <class R, class... P, size_t... Is>
  448. void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
  449. r_error.error = GDEXTENSION_CALL_OK;
  450. #ifdef DEBUG_METHODS_ENABLED
  451. r_ret = (p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
  452. #else
  453. r_ret = (p_method)(VariantCaster<P>::cast(*p_args[Is])...);
  454. #endif
  455. }
  456. template <class R, class... P>
  457. void call_with_variant_args_static_ret_dv(R (*p_method)(P...), GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
  458. #ifdef DEBUG_ENABLED
  459. if ((size_t)p_argcount > sizeof...(P)) {
  460. r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
  461. r_error.argument = sizeof...(P);
  462. return;
  463. }
  464. #endif
  465. int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
  466. int32_t dvs = default_values.size();
  467. #ifdef DEBUG_ENABLED
  468. if (missing > dvs) {
  469. r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
  470. r_error.argument = sizeof...(P);
  471. return;
  472. }
  473. #endif
  474. Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
  475. std::array<const Variant *, sizeof...(P)> argsp;
  476. for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
  477. if (i < p_argcount) {
  478. args[i] = Variant(p_args[i]);
  479. } else {
  480. args[i] = default_values[i - p_argcount + (dvs - missing)];
  481. }
  482. argsp[i] = &args[i];
  483. }
  484. call_with_variant_args_static_ret(p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
  485. }
  486. template <class R, class... P, size_t... Is>
  487. void call_with_ptr_args_static_method_ret_helper(R (*p_method)(P...), GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
  488. PtrToArg<R>::encode(p_method(PtrToArg<P>::convert(p_args[Is])...), r_ret);
  489. }
  490. template <class R, class... P>
  491. void call_with_ptr_args_static_method_ret(R (*p_method)(P...), GDExtensionConstTypePtr *p_args, void *r_ret) {
  492. call_with_ptr_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
  493. }
  494. #if defined(__GNUC__) && !defined(__clang__)
  495. #pragma GCC diagnostic pop
  496. #endif
  497. } // namespace godot
  498. #include <godot_cpp/classes/global_constants_binds.hpp>
  499. #include <godot_cpp/variant/builtin_binds.hpp>
  500. #endif // GODOT_BINDER_COMMON_HPP