method_bind.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /*************************************************************************/
  2. /* method_bind.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_CPP_METHOD_BIND_HPP
  31. #define GODOT_CPP_METHOD_BIND_HPP
  32. #include <godot_cpp/core/binder_common.hpp>
  33. #include <godot_cpp/core/type_info.hpp>
  34. #include <godot_cpp/core/memory.hpp>
  35. #include <godot/gdnative_interface.h>
  36. #include <godot_cpp/classes/global_constants.hpp>
  37. #include <string>
  38. #include <vector>
  39. #include <iostream>
  40. namespace godot {
  41. class MethodBind {
  42. const char *name = nullptr;
  43. const char *instance_class = nullptr;
  44. int argument_count = 0;
  45. uint32_t hint_flags = METHOD_FLAGS_DEFAULT;
  46. bool _static = false;
  47. bool _is_const = false;
  48. bool _has_return = false;
  49. bool _vararg = false;
  50. std::vector<std::string> argument_names;
  51. GDNativeVariantType *argument_types = nullptr;
  52. std::vector<Variant> default_arguments;
  53. protected:
  54. virtual GDNativeVariantType gen_argument_type(int p_arg) const = 0;
  55. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const = 0;
  56. void generate_argument_types(int p_count);
  57. void set_const(bool p_const);
  58. void set_return(bool p_return);
  59. void set_static(bool p_static);
  60. void set_vararg(bool p_vararg);
  61. void set_argument_count(int p_count);
  62. public:
  63. const char *get_name() const;
  64. void set_name(const char *p_name);
  65. _FORCE_INLINE_ int get_default_argument_count() const { return (int)default_arguments.size(); }
  66. _FORCE_INLINE_ const std::vector<Variant> &get_default_arguments() const { return default_arguments; }
  67. _FORCE_INLINE_ Variant has_default_argument(int p_arg) const {
  68. int idx = p_arg - (argument_count - (int)default_arguments.size());
  69. if (idx < 0 || idx >= default_arguments.size()) {
  70. return false;
  71. } else {
  72. return true;
  73. }
  74. }
  75. _FORCE_INLINE_ Variant get_default_argument(int p_arg) const {
  76. int idx = p_arg - (argument_count - (int)default_arguments.size());
  77. if (idx < 0 || idx >= default_arguments.size()) {
  78. return Variant();
  79. } else {
  80. return default_arguments[idx];
  81. }
  82. }
  83. _FORCE_INLINE_ const char *get_instance_class() const { return instance_class; }
  84. _FORCE_INLINE_ void set_instance_class(const char *p_class) { instance_class = p_class; }
  85. _FORCE_INLINE_ int get_argument_count() const { return argument_count; };
  86. _FORCE_INLINE_ bool is_const() const { return _is_const; }
  87. _FORCE_INLINE_ bool is_static() const { return _static; }
  88. _FORCE_INLINE_ bool is_vararg() const { return _vararg; }
  89. _FORCE_INLINE_ bool has_return() const { return _has_return; }
  90. _FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags | (is_const() ? GDNATIVE_EXTENSION_METHOD_FLAG_CONST : 0) | (is_vararg() ? GDNATIVE_EXTENSION_METHOD_FLAG_VARARG : 0) | (is_static() ? GDNATIVE_EXTENSION_METHOD_FLAG_STATIC : 0); }
  91. _FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; }
  92. void set_argument_names(const std::vector<std::string> &p_names);
  93. std::vector<std::string> get_argument_names() const;
  94. void set_default_arguments(const std::vector<Variant> &p_default_arguments) { default_arguments = p_default_arguments; }
  95. _FORCE_INLINE_ GDNativeVariantType get_argument_type(int p_argument) const {
  96. ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, GDNATIVE_VARIANT_TYPE_NIL);
  97. return argument_types[p_argument + 1];
  98. }
  99. GDNativePropertyInfo get_argument_info(int p_argument) const;
  100. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const = 0;
  101. virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const = 0;
  102. virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return) const = 0;
  103. // Extension info.
  104. static GDNativeVariantType bind_get_argument_type(void *p_method_userdata, int32_t p_argument);
  105. static void bind_get_argument_info(void *p_method_userdata, int32_t p_argument, GDNativePropertyInfo *r_info);
  106. static GDNativeExtensionClassMethodArgumentMetadata bind_get_argument_metadata(void *p_method_userdata, int32_t p_argument);
  107. static void bind_call(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
  108. static void bind_ptrcall(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return);
  109. virtual ~MethodBind();
  110. };
  111. template <class Derived, class T, class R, bool should_returns>
  112. class MethodBindVarArgBase : public MethodBind {
  113. protected:
  114. R(T::*method)
  115. (const Variant **, GDNativeInt, GDNativeCallError &);
  116. std::vector<GDNativePropertyInfo> arguments;
  117. public:
  118. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
  119. if (p_arg < 0) {
  120. return _gen_return_type_info();
  121. } else if (p_arg < arguments.size()) {
  122. return arguments[p_arg];
  123. } else {
  124. return make_property_info(GDNATIVE_VARIANT_TYPE_NIL, "vararg", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
  125. }
  126. }
  127. virtual GDNativeVariantType gen_argument_type(int p_arg) const {
  128. return static_cast<GDNativeVariantType>(gen_argument_type_info(p_arg).type);
  129. }
  130. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int) const {
  131. return GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
  132. }
  133. virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return) const {
  134. ERR_FAIL(); // Can't call.
  135. }
  136. static _FORCE_INLINE_ char *_alloc_and_copy_cstr(const char *p_str) {
  137. size_t size = strlen(p_str) + 1;
  138. char *ret = reinterpret_cast<char *>(memalloc(size));
  139. memcpy(ret, p_str, size);
  140. return ret;
  141. }
  142. MethodBindVarArgBase(
  143. R (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &),
  144. const MethodInfo &p_method_info,
  145. bool p_return_nil_is_variant) :
  146. method(p_method) {
  147. set_vararg(true);
  148. set_const(true);
  149. set_argument_count(p_method_info.arguments.size());
  150. if (p_method_info.arguments.size()) {
  151. std::vector<std::string> names;
  152. names.reserve(p_method_info.arguments.size());
  153. for (int i = 0; i < p_method_info.arguments.size(); i++) {
  154. names.push_back(p_method_info.arguments[i].name.utf8().get_data());
  155. arguments.push_back(GDNativePropertyInfo{
  156. static_cast<uint32_t>(p_method_info.arguments[i].type), // uint32_t type;
  157. _alloc_and_copy_cstr(p_method_info.arguments[i].name.utf8().get_data()), // const char *name;
  158. _alloc_and_copy_cstr(p_method_info.arguments[i].class_name.utf8().get_data()), // const char *class_name;
  159. p_method_info.arguments[i].hint, // NONE //uint32_t hint;
  160. _alloc_and_copy_cstr(p_method_info.arguments[i].hint_string.utf8().get_data()), // const char *hint_string;
  161. p_method_info.arguments[i].usage, // DEFAULT //uint32_t usage;
  162. });
  163. }
  164. set_argument_names(names);
  165. }
  166. generate_argument_types((int)p_method_info.arguments.size());
  167. set_return(should_returns);
  168. }
  169. ~MethodBindVarArgBase() {
  170. for (GDNativePropertyInfo &arg : arguments) {
  171. memfree(const_cast<char *>(arg.name));
  172. memfree(const_cast<char *>(arg.class_name));
  173. memfree(const_cast<char *>(arg.hint_string));
  174. }
  175. }
  176. private:
  177. GDNativePropertyInfo _gen_return_type_info() const {
  178. return reinterpret_cast<const Derived *>(this)->_gen_return_type_info_impl();
  179. }
  180. };
  181. template <class T>
  182. class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false> {
  183. friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>;
  184. public:
  185. virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
  186. (static_cast<T *>(p_instance)->*MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>::method)((const Variant **)p_args, p_argument_count, r_error);
  187. return {};
  188. }
  189. MethodBindVarArgT(
  190. void (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &),
  191. const MethodInfo &p_method_info,
  192. bool p_return_nil_is_variant) :
  193. MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>(p_method, p_method_info, p_return_nil_is_variant) {
  194. }
  195. private:
  196. GDNativePropertyInfo _gen_return_type_info_impl() const {
  197. return {};
  198. }
  199. };
  200. template <class T>
  201. MethodBind *create_vararg_method_bind(void (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
  202. MethodBind *a = memnew((MethodBindVarArgT<T>)(p_method, p_info, p_return_nil_is_variant));
  203. a->set_instance_class(T::get_class_static());
  204. return a;
  205. }
  206. template <class T, class R>
  207. class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true> {
  208. friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>;
  209. public:
  210. virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
  211. return (static_cast<T *>(p_instance)->*MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>::method)((const Variant **)p_args, p_argument_count, r_error);
  212. }
  213. MethodBindVarArgTR(
  214. R (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &),
  215. const MethodInfo &p_info,
  216. bool p_return_nil_is_variant) :
  217. MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>(p_method, p_info, p_return_nil_is_variant) {
  218. }
  219. private:
  220. GDNativePropertyInfo _gen_return_type_info_impl() const {
  221. return GetTypeInfo<R>::get_class_info();
  222. }
  223. };
  224. template <class T, class R>
  225. MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
  226. MethodBind *a = memnew((MethodBindVarArgTR<T, R>)(p_method, p_info, p_return_nil_is_variant));
  227. a->set_instance_class(T::get_class_static());
  228. return a;
  229. }
  230. #ifndef TYPED_METHOD_BIND
  231. class ___UnexistingClass;
  232. #define MB_T ___UnexistingClass
  233. #else
  234. #define MB_T T
  235. #endif
  236. // No return, not const.
  237. #ifdef TYPED_METHOD_BIND
  238. template <class T, class... P>
  239. #else
  240. template <class... P>
  241. #endif // TYPED_METHOD_BIND
  242. class MethodBindT : public MethodBind {
  243. void (MB_T::*method)(P...);
  244. protected:
  245. // GCC raises warnings in the case P = {} as the comparison is always false...
  246. #if defined(__GNUC__) && !defined(__clang__)
  247. #pragma GCC diagnostic push
  248. #pragma GCC diagnostic ignored "-Wlogical-op"
  249. #endif
  250. virtual GDNativeVariantType gen_argument_type(int p_arg) const {
  251. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  252. return call_get_argument_type<P...>(p_arg);
  253. } else {
  254. return GDNATIVE_VARIANT_TYPE_NIL;
  255. }
  256. }
  257. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
  258. GDNativePropertyInfo pi;
  259. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  260. call_get_argument_type_info<P...>(p_arg, pi);
  261. } else {
  262. pi = GDNativePropertyInfo();
  263. }
  264. return pi;
  265. }
  266. #if defined(__GNUC__) && !defined(__clang__)
  267. #pragma GCC diagnostic pop
  268. #endif
  269. public:
  270. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
  271. return call_get_argument_metadata<P...>(p_argument);
  272. }
  273. virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
  274. #ifdef TYPED_METHOD_BIND
  275. call_with_variant_args_dv(static_cast<T *>(p_instance), method, p_args, (int)p_argument_count, r_error, get_default_arguments());
  276. #else
  277. call_with_variant_args_dv(reinterpret_cast<MB_T *>(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments());
  278. #endif
  279. return Variant();
  280. }
  281. virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
  282. #ifdef TYPED_METHOD_BIND
  283. call_with_ptr_args<T, P...>(static_cast<T *>(p_instance), method, p_args, nullptr);
  284. #else
  285. call_with_ptr_args<MB_T, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, nullptr);
  286. #endif // TYPED_METHOD_BIND
  287. }
  288. MethodBindT(void (MB_T::*p_method)(P...)) {
  289. method = p_method;
  290. generate_argument_types(sizeof...(P));
  291. set_argument_count(sizeof...(P));
  292. }
  293. };
  294. template <class T, class... P>
  295. MethodBind *create_method_bind(void (T::*p_method)(P...)) {
  296. #ifdef TYPED_METHOD_BIND
  297. MethodBind *a = memnew((MethodBindT<T, P...>)(p_method));
  298. #else
  299. MethodBind *a = memnew((MethodBindT<P...>)(reinterpret_cast<void (MB_T::*)(P...)>(p_method)));
  300. #endif // TYPED_METHOD_BIND
  301. a->set_instance_class(T::get_class_static());
  302. return a;
  303. }
  304. // No return, const.
  305. #ifdef TYPED_METHOD_BIND
  306. template <class T, class... P>
  307. #else
  308. template <class... P>
  309. #endif // TYPED_METHOD_BIND
  310. class MethodBindTC : public MethodBind {
  311. void (MB_T::*method)(P...) const;
  312. protected:
  313. // GCC raises warnings in the case P = {} as the comparison is always false...
  314. #if defined(__GNUC__) && !defined(__clang__)
  315. #pragma GCC diagnostic push
  316. #pragma GCC diagnostic ignored "-Wlogical-op"
  317. #endif
  318. virtual GDNativeVariantType gen_argument_type(int p_arg) const {
  319. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  320. return call_get_argument_type<P...>(p_arg);
  321. } else {
  322. return GDNATIVE_VARIANT_TYPE_NIL;
  323. }
  324. }
  325. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
  326. GDNativePropertyInfo pi;
  327. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  328. call_get_argument_type_info<P...>(p_arg, pi);
  329. } else {
  330. pi = GDNativePropertyInfo();
  331. }
  332. return pi;
  333. }
  334. #if defined(__GNUC__) && !defined(__clang__)
  335. #pragma GCC diagnostic pop
  336. #endif
  337. public:
  338. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
  339. return call_get_argument_metadata<P...>(p_argument);
  340. }
  341. virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
  342. #ifdef TYPED_METHOD_BIND
  343. call_with_variant_argsc_dv(static_cast<T *>(p_instance), method, p_args, (int)p_argument_count, r_error, get_default_arguments());
  344. #else
  345. call_with_variant_argsc_dv(reinterpret_cast<MB_T *>(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments());
  346. #endif
  347. return Variant();
  348. }
  349. virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
  350. #ifdef TYPED_METHOD_BIND
  351. call_with_ptr_args<T, P...>(static_cast<T *>(p_instance), method, p_args, nullptr);
  352. #else
  353. call_with_ptr_args<MB_T, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, nullptr);
  354. #endif // TYPED_METHOD_BIND
  355. }
  356. MethodBindTC(void (MB_T::*p_method)(P...) const) {
  357. method = p_method;
  358. generate_argument_types(sizeof...(P));
  359. set_argument_count(sizeof...(P));
  360. }
  361. };
  362. template <class T, class... P>
  363. MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
  364. #ifdef TYPED_METHOD_BIND
  365. MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method));
  366. #else
  367. MethodBind *a = memnew((MethodBindTC<P...>)(reinterpret_cast<void (MB_T::*)(P...) const>(p_method)));
  368. #endif // TYPED_METHOD_BIND
  369. a->set_instance_class(T::get_class_static());
  370. return a;
  371. }
  372. // Return, not const.
  373. #ifdef TYPED_METHOD_BIND
  374. template <class T, class R, class... P>
  375. #else
  376. template <class R, class... P>
  377. #endif // TYPED_METHOD_BIND
  378. class MethodBindTR : public MethodBind {
  379. R(MB_T::*method)
  380. (P...);
  381. protected:
  382. // GCC raises warnings in the case P = {} as the comparison is always false...
  383. #if defined(__GNUC__) && !defined(__clang__)
  384. #pragma GCC diagnostic push
  385. #pragma GCC diagnostic ignored "-Wlogical-op"
  386. #endif
  387. virtual GDNativeVariantType gen_argument_type(int p_arg) const {
  388. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  389. return call_get_argument_type<P...>(p_arg);
  390. } else {
  391. return GDNativeVariantType(GetTypeInfo<R>::VARIANT_TYPE);
  392. }
  393. }
  394. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
  395. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  396. GDNativePropertyInfo pi;
  397. call_get_argument_type_info<P...>(p_arg, pi);
  398. return pi;
  399. } else {
  400. return GetTypeInfo<R>::get_class_info();
  401. }
  402. }
  403. #if defined(__GNUC__) && !defined(__clang__)
  404. #pragma GCC diagnostic pop
  405. #endif
  406. public:
  407. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
  408. if (p_argument >= 0) {
  409. return call_get_argument_metadata<P...>(p_argument);
  410. } else {
  411. return GetTypeInfo<R>::METADATA;
  412. }
  413. }
  414. virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
  415. Variant ret;
  416. #ifdef TYPED_METHOD_BIND
  417. call_with_variant_args_ret_dv(static_cast<T *>(p_instance), method, p_args, (int)p_argument_count, ret, r_error, get_default_arguments());
  418. #else
  419. call_with_variant_args_ret_dv((MB_T *)p_instance, method, p_args, p_argument_count, ret, r_error, get_default_arguments());
  420. #endif
  421. return ret;
  422. }
  423. virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
  424. #ifdef TYPED_METHOD_BIND
  425. call_with_ptr_args<T, R, P...>(static_cast<T *>(p_instance), method, p_args, r_ret);
  426. #else
  427. call_with_ptr_args<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, r_ret);
  428. #endif // TYPED_METHOD_BIND
  429. }
  430. MethodBindTR(R (MB_T::*p_method)(P...)) {
  431. method = p_method;
  432. generate_argument_types(sizeof...(P));
  433. set_argument_count(sizeof...(P));
  434. set_return(true);
  435. }
  436. };
  437. template <class T, class R, class... P>
  438. MethodBind *create_method_bind(R (T::*p_method)(P...)) {
  439. #ifdef TYPED_METHOD_BIND
  440. MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method));
  441. #else
  442. MethodBind *a = memnew((MethodBindTR<R, P...>)(reinterpret_cast<R (MB_T::*)(P...)>(p_method)));
  443. #endif // TYPED_METHOD_BIND
  444. a->set_instance_class(T::get_class_static());
  445. return a;
  446. }
  447. // Return, const.
  448. #ifdef TYPED_METHOD_BIND
  449. template <class T, class R, class... P>
  450. #else
  451. template <class R, class... P>
  452. #endif // TYPED_METHOD_BIND
  453. class MethodBindTRC : public MethodBind {
  454. R(MB_T::*method)
  455. (P...) const;
  456. protected:
  457. // GCC raises warnings in the case P = {} as the comparison is always false...
  458. #if defined(__GNUC__) && !defined(__clang__)
  459. #pragma GCC diagnostic push
  460. #pragma GCC diagnostic ignored "-Wlogical-op"
  461. #endif
  462. virtual GDNativeVariantType gen_argument_type(int p_arg) const {
  463. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  464. return call_get_argument_type<P...>(p_arg);
  465. } else {
  466. return GDNativeVariantType(GetTypeInfo<R>::VARIANT_TYPE);
  467. }
  468. }
  469. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
  470. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  471. GDNativePropertyInfo pi;
  472. call_get_argument_type_info<P...>(p_arg, pi);
  473. return pi;
  474. } else {
  475. return GetTypeInfo<R>::get_class_info();
  476. }
  477. }
  478. #if defined(__GNUC__) && !defined(__clang__)
  479. #pragma GCC diagnostic pop
  480. #endif
  481. public:
  482. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
  483. if (p_argument >= 0) {
  484. return call_get_argument_metadata<P...>(p_argument);
  485. } else {
  486. return GetTypeInfo<R>::METADATA;
  487. }
  488. }
  489. virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
  490. Variant ret;
  491. #ifdef TYPED_METHOD_BIND
  492. call_with_variant_args_retc_dv(static_cast<T *>(p_instance), method, p_args, (int)p_argument_count, ret, r_error, get_default_arguments());
  493. #else
  494. call_with_variant_args_retc_dv((MB_T *)p_instance, method, p_args, p_argument_count, ret, r_error, get_default_arguments());
  495. #endif
  496. return ret;
  497. }
  498. virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
  499. #ifdef TYPED_METHOD_BIND
  500. call_with_ptr_args<T, R, P...>(static_cast<T *>(p_instance), method, p_args, r_ret);
  501. #else
  502. call_with_ptr_args<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, r_ret);
  503. #endif // TYPED_METHOD_BIND
  504. }
  505. MethodBindTRC(R (MB_T::*p_method)(P...) const) {
  506. method = p_method;
  507. generate_argument_types(sizeof...(P));
  508. set_argument_count(sizeof...(P));
  509. set_return(true);
  510. }
  511. };
  512. template <class T, class R, class... P>
  513. MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
  514. #ifdef TYPED_METHOD_BIND
  515. MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method));
  516. #else
  517. MethodBind *a = memnew((MethodBindTRC<R, P...>)(reinterpret_cast<R (MB_T::*)(P...) const>(p_method)));
  518. #endif // TYPED_METHOD_BIND
  519. a->set_instance_class(T::get_class_static());
  520. return a;
  521. }
  522. // STATIC BINDS
  523. // no return
  524. template <class... P>
  525. class MethodBindTS : public MethodBind {
  526. void (*function)(P...);
  527. protected:
  528. // GCC raises warnings in the case P = {} as the comparison is always false...
  529. #if defined(__GNUC__) && !defined(__clang__)
  530. #pragma GCC diagnostic push
  531. #pragma GCC diagnostic ignored "-Wlogical-op"
  532. #endif
  533. virtual GDNativeVariantType gen_argument_type(int p_arg) const {
  534. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  535. return call_get_argument_type<P...>(p_arg);
  536. } else {
  537. return GDNATIVE_VARIANT_TYPE_NIL;
  538. }
  539. }
  540. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
  541. GDNativePropertyInfo pi;
  542. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  543. call_get_argument_type_info<P...>(p_arg, pi);
  544. } else {
  545. pi = GDNativePropertyInfo();
  546. }
  547. return pi;
  548. }
  549. #if defined(__GNUC__) && !defined(__clang__)
  550. #pragma GCC diagnostic pop
  551. #endif
  552. public:
  553. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_arg) const {
  554. return call_get_argument_metadata<P...>(p_arg);
  555. }
  556. virtual Variant call(GDExtensionClassInstancePtr p_object, const GDNativeVariantPtr *p_args, const GDNativeInt p_arg_count, GDNativeCallError &r_error) const {
  557. (void)p_object; // unused
  558. call_with_variant_args_static_dv(function, p_args, p_arg_count, r_error, get_default_arguments());
  559. return Variant();
  560. }
  561. virtual void ptrcall(GDExtensionClassInstancePtr p_object, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
  562. (void)p_object;
  563. (void)r_ret;
  564. call_with_ptr_args_static_method(function, p_args);
  565. }
  566. MethodBindTS(void (*p_function)(P...)) {
  567. function = p_function;
  568. generate_argument_types(sizeof...(P));
  569. set_argument_count(sizeof...(P));
  570. set_static(true);
  571. }
  572. };
  573. template <class... P>
  574. MethodBind *create_static_method_bind(void (*p_method)(P...)) {
  575. MethodBind *a = memnew((MethodBindTS<P...>)(p_method));
  576. return a;
  577. }
  578. // return
  579. template <class R, class... P>
  580. class MethodBindTRS : public MethodBind {
  581. R(*function)
  582. (P...);
  583. protected:
  584. // GCC raises warnings in the case P = {} as the comparison is always false...
  585. #if defined(__GNUC__) && !defined(__clang__)
  586. #pragma GCC diagnostic push
  587. #pragma GCC diagnostic ignored "-Wlogical-op"
  588. #endif
  589. virtual GDNativeVariantType gen_argument_type(int p_arg) const {
  590. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  591. return call_get_argument_type<P...>(p_arg);
  592. } else {
  593. return GDNativeVariantType(GetTypeInfo<R>::VARIANT_TYPE);
  594. }
  595. }
  596. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
  597. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  598. GDNativePropertyInfo pi;
  599. call_get_argument_type_info<P...>(p_arg, pi);
  600. return pi;
  601. } else {
  602. return GetTypeInfo<R>::get_class_info();
  603. }
  604. }
  605. #if defined(__GNUC__) && !defined(__clang__)
  606. #pragma GCC diagnostic pop
  607. #endif
  608. public:
  609. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_arg) const {
  610. if (p_arg >= 0) {
  611. return call_get_argument_metadata<P...>(p_arg);
  612. } else {
  613. return GetTypeInfo<R>::METADATA;
  614. }
  615. }
  616. virtual Variant call(GDExtensionClassInstancePtr p_object, const GDNativeVariantPtr *p_args, const GDNativeInt p_arg_count, GDNativeCallError &r_error) const {
  617. Variant ret;
  618. call_with_variant_args_static_ret_dv(function, p_args, p_arg_count, ret, r_error, get_default_arguments());
  619. return ret;
  620. }
  621. virtual void ptrcall(GDExtensionClassInstancePtr p_object, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
  622. (void)p_object;
  623. call_with_ptr_args_static_method_ret(function, p_args, r_ret);
  624. }
  625. MethodBindTRS(R (*p_function)(P...)) {
  626. function = p_function;
  627. generate_argument_types(sizeof...(P));
  628. set_argument_count(sizeof...(P));
  629. set_static(true);
  630. set_return(true);
  631. }
  632. };
  633. template <class R, class... P>
  634. MethodBind *create_static_method_bind(R (*p_method)(P...)) {
  635. MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method));
  636. return a;
  637. }
  638. } // namespace godot
  639. #endif // ! GODOT_CPP_METHOD_BIND_HPP