method_bind.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  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. MethodInfo method_info;
  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 < method_info.arguments.size()) {
  122. return method_info.arguments[p_arg];
  123. } else {
  124. return PropertyInfo(Variant::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. MethodBindVarArgBase(
  137. R (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &),
  138. const MethodInfo &p_method_info,
  139. bool p_return_nil_is_variant) :
  140. method(p_method), method_info(p_method_info) {
  141. set_vararg(true);
  142. set_const(true);
  143. set_argument_count(method_info.arguments.size());
  144. if (method_info.arguments.size()) {
  145. std::vector<std::string> names;
  146. names.reserve(method_info.arguments.size());
  147. for (int i = 0; i < method_info.arguments.size(); i++) {
  148. names.push_back(method_info.arguments[i].name);
  149. }
  150. set_argument_names(names);
  151. }
  152. if (p_return_nil_is_variant) {
  153. method_info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
  154. }
  155. generate_argument_types((int)method_info.arguments.size());
  156. set_return(should_returns);
  157. }
  158. private:
  159. GDNativePropertyInfo _gen_return_type_info() const {
  160. return reinterpret_cast<const Derived *>(this)->_gen_return_type_info_impl();
  161. }
  162. };
  163. template <class T>
  164. class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false> {
  165. friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>;
  166. public:
  167. virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
  168. (static_cast<T *>(p_instance)->*MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>::method)((const Variant **)p_args, p_argument_count, r_error);
  169. return {};
  170. }
  171. MethodBindVarArgT(
  172. void (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &),
  173. const MethodInfo &p_method_info,
  174. bool p_return_nil_is_variant) :
  175. MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>(p_method, p_method_info, p_return_nil_is_variant) {
  176. }
  177. private:
  178. GDNativePropertyInfo _gen_return_type_info_impl() const {
  179. return {};
  180. }
  181. };
  182. template <class T>
  183. MethodBind *create_vararg_method_bind(void (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
  184. MethodBind *a = memnew((MethodBindVarArgT<T>)(p_method, p_info, p_return_nil_is_variant));
  185. a->set_instance_class(T::get_class_static());
  186. return a;
  187. }
  188. template <class T, class R>
  189. class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true> {
  190. friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>;
  191. public:
  192. virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
  193. return (static_cast<T *>(p_instance)->*MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>::method)((const Variant **)p_args, p_argument_count, r_error);
  194. }
  195. MethodBindVarArgTR(
  196. R (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &),
  197. const MethodInfo &p_info,
  198. bool p_return_nil_is_variant) :
  199. MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>(p_method, p_info, p_return_nil_is_variant) {
  200. }
  201. private:
  202. GDNativePropertyInfo _gen_return_type_info_impl() const {
  203. return GetTypeInfo<R>::get_class_info();
  204. }
  205. };
  206. template <class T, class R>
  207. MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
  208. MethodBind *a = memnew((MethodBindVarArgTR<T, R>)(p_method, p_info, p_return_nil_is_variant));
  209. a->set_instance_class(T::get_class_static());
  210. return a;
  211. }
  212. #ifndef TYPED_METHOD_BIND
  213. class ___UnexistingClass;
  214. #define MB_T ___UnexistingClass
  215. #else
  216. #define MB_T T
  217. #endif
  218. // No return, not const.
  219. #ifdef TYPED_METHOD_BIND
  220. template <class T, class... P>
  221. #else
  222. template <class... P>
  223. #endif // TYPED_METHOD_BIND
  224. class MethodBindT : public MethodBind {
  225. void (MB_T::*method)(P...);
  226. protected:
  227. // GCC raises warnings in the case P = {} as the comparison is always false...
  228. #if defined(__GNUC__) && !defined(__clang__)
  229. #pragma GCC diagnostic push
  230. #pragma GCC diagnostic ignored "-Wlogical-op"
  231. #endif
  232. virtual GDNativeVariantType gen_argument_type(int p_arg) const {
  233. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  234. return call_get_argument_type<P...>(p_arg);
  235. } else {
  236. return GDNATIVE_VARIANT_TYPE_NIL;
  237. }
  238. }
  239. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
  240. GDNativePropertyInfo pi;
  241. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  242. call_get_argument_type_info<P...>(p_arg, pi);
  243. } else {
  244. pi = PropertyInfo();
  245. }
  246. return pi;
  247. }
  248. #if defined(__GNUC__) && !defined(__clang__)
  249. #pragma GCC diagnostic pop
  250. #endif
  251. public:
  252. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
  253. return call_get_argument_metadata<P...>(p_argument);
  254. }
  255. virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
  256. #ifdef TYPED_METHOD_BIND
  257. call_with_variant_args_dv(static_cast<T *>(p_instance), method, p_args, (int)p_argument_count, r_error, get_default_arguments());
  258. #else
  259. call_with_variant_args_dv(reinterpret_cast<MB_T *>(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments());
  260. #endif
  261. return Variant();
  262. }
  263. virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
  264. #ifdef TYPED_METHOD_BIND
  265. call_with_ptr_args<T, P...>(static_cast<T *>(p_instance), method, p_args, nullptr);
  266. #else
  267. call_with_ptr_args<MB_T, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, nullptr);
  268. #endif // TYPED_METHOD_BIND
  269. }
  270. MethodBindT(void (MB_T::*p_method)(P...)) {
  271. method = p_method;
  272. generate_argument_types(sizeof...(P));
  273. set_argument_count(sizeof...(P));
  274. }
  275. };
  276. template <class T, class... P>
  277. MethodBind *create_method_bind(void (T::*p_method)(P...)) {
  278. #ifdef TYPED_METHOD_BIND
  279. MethodBind *a = memnew((MethodBindT<T, P...>)(p_method));
  280. #else
  281. MethodBind *a = memnew((MethodBindT<P...>)(reinterpret_cast<void (MB_T::*)(P...)>(p_method)));
  282. #endif // TYPED_METHOD_BIND
  283. a->set_instance_class(T::get_class_static());
  284. return a;
  285. }
  286. // No return, const.
  287. #ifdef TYPED_METHOD_BIND
  288. template <class T, class... P>
  289. #else
  290. template <class... P>
  291. #endif // TYPED_METHOD_BIND
  292. class MethodBindTC : public MethodBind {
  293. void (MB_T::*method)(P...) const;
  294. protected:
  295. // GCC raises warnings in the case P = {} as the comparison is always false...
  296. #if defined(__GNUC__) && !defined(__clang__)
  297. #pragma GCC diagnostic push
  298. #pragma GCC diagnostic ignored "-Wlogical-op"
  299. #endif
  300. virtual GDNativeVariantType gen_argument_type(int p_arg) const {
  301. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  302. return call_get_argument_type<P...>(p_arg);
  303. } else {
  304. return GDNATIVE_VARIANT_TYPE_NIL;
  305. }
  306. }
  307. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
  308. GDNativePropertyInfo pi;
  309. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  310. call_get_argument_type_info<P...>(p_arg, pi);
  311. } else {
  312. pi = PropertyInfo();
  313. }
  314. return pi;
  315. }
  316. #if defined(__GNUC__) && !defined(__clang__)
  317. #pragma GCC diagnostic pop
  318. #endif
  319. public:
  320. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
  321. return call_get_argument_metadata<P...>(p_argument);
  322. }
  323. virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
  324. #ifdef TYPED_METHOD_BIND
  325. call_with_variant_argsc_dv(static_cast<T *>(p_instance), method, p_args, (int)p_argument_count, r_error, get_default_arguments());
  326. #else
  327. call_with_variant_argsc_dv(reinterpret_cast<MB_T *>(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments());
  328. #endif
  329. return Variant();
  330. }
  331. virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
  332. #ifdef TYPED_METHOD_BIND
  333. call_with_ptr_args<T, P...>(static_cast<T *>(p_instance), method, p_args, nullptr);
  334. #else
  335. call_with_ptr_args<MB_T, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, nullptr);
  336. #endif // TYPED_METHOD_BIND
  337. }
  338. MethodBindTC(void (MB_T::*p_method)(P...) const) {
  339. method = p_method;
  340. generate_argument_types(sizeof...(P));
  341. set_argument_count(sizeof...(P));
  342. }
  343. };
  344. template <class T, class... P>
  345. MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
  346. #ifdef TYPED_METHOD_BIND
  347. MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method));
  348. #else
  349. MethodBind *a = memnew((MethodBindTC<P...>)(reinterpret_cast<void (MB_T::*)(P...) const>(p_method)));
  350. #endif // TYPED_METHOD_BIND
  351. a->set_instance_class(T::get_class_static());
  352. return a;
  353. }
  354. // Return, not const.
  355. #ifdef TYPED_METHOD_BIND
  356. template <class T, class R, class... P>
  357. #else
  358. template <class R, class... P>
  359. #endif // TYPED_METHOD_BIND
  360. class MethodBindTR : public MethodBind {
  361. R(MB_T::*method)
  362. (P...);
  363. protected:
  364. // GCC raises warnings in the case P = {} as the comparison is always false...
  365. #if defined(__GNUC__) && !defined(__clang__)
  366. #pragma GCC diagnostic push
  367. #pragma GCC diagnostic ignored "-Wlogical-op"
  368. #endif
  369. virtual GDNativeVariantType gen_argument_type(int p_arg) const {
  370. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  371. return call_get_argument_type<P...>(p_arg);
  372. } else {
  373. return GDNativeVariantType(GetTypeInfo<R>::VARIANT_TYPE);
  374. }
  375. }
  376. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
  377. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  378. GDNativePropertyInfo pi;
  379. call_get_argument_type_info<P...>(p_arg, pi);
  380. return pi;
  381. } else {
  382. return GetTypeInfo<R>::get_class_info();
  383. }
  384. }
  385. #if defined(__GNUC__) && !defined(__clang__)
  386. #pragma GCC diagnostic pop
  387. #endif
  388. public:
  389. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
  390. if (p_argument >= 0) {
  391. return call_get_argument_metadata<P...>(p_argument);
  392. } else {
  393. return GetTypeInfo<R>::METADATA;
  394. }
  395. }
  396. virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
  397. Variant ret;
  398. #ifdef TYPED_METHOD_BIND
  399. call_with_variant_args_ret_dv(static_cast<T *>(p_instance), method, p_args, (int)p_argument_count, ret, r_error, get_default_arguments());
  400. #else
  401. call_with_variant_args_ret_dv((MB_T *)p_instance, method, p_args, p_argument_count, ret, r_error, get_default_arguments());
  402. #endif
  403. return ret;
  404. }
  405. virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
  406. #ifdef TYPED_METHOD_BIND
  407. call_with_ptr_args<T, R, P...>(static_cast<T *>(p_instance), method, p_args, r_ret);
  408. #else
  409. call_with_ptr_args<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, r_ret);
  410. #endif // TYPED_METHOD_BIND
  411. }
  412. MethodBindTR(R (MB_T::*p_method)(P...)) {
  413. method = p_method;
  414. generate_argument_types(sizeof...(P));
  415. set_argument_count(sizeof...(P));
  416. set_return(true);
  417. }
  418. };
  419. template <class T, class R, class... P>
  420. MethodBind *create_method_bind(R (T::*p_method)(P...)) {
  421. #ifdef TYPED_METHOD_BIND
  422. MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method));
  423. #else
  424. MethodBind *a = memnew((MethodBindTR<R, P...>)(reinterpret_cast<R (MB_T::*)(P...)>(p_method)));
  425. #endif // TYPED_METHOD_BIND
  426. a->set_instance_class(T::get_class_static());
  427. return a;
  428. }
  429. // Return, const.
  430. #ifdef TYPED_METHOD_BIND
  431. template <class T, class R, class... P>
  432. #else
  433. template <class R, class... P>
  434. #endif // TYPED_METHOD_BIND
  435. class MethodBindTRC : public MethodBind {
  436. R(MB_T::*method)
  437. (P...) const;
  438. protected:
  439. // GCC raises warnings in the case P = {} as the comparison is always false...
  440. #if defined(__GNUC__) && !defined(__clang__)
  441. #pragma GCC diagnostic push
  442. #pragma GCC diagnostic ignored "-Wlogical-op"
  443. #endif
  444. virtual GDNativeVariantType gen_argument_type(int p_arg) const {
  445. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  446. return call_get_argument_type<P...>(p_arg);
  447. } else {
  448. return GDNativeVariantType(GetTypeInfo<R>::VARIANT_TYPE);
  449. }
  450. }
  451. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
  452. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  453. GDNativePropertyInfo pi;
  454. call_get_argument_type_info<P...>(p_arg, pi);
  455. return pi;
  456. } else {
  457. return GetTypeInfo<R>::get_class_info();
  458. }
  459. }
  460. #if defined(__GNUC__) && !defined(__clang__)
  461. #pragma GCC diagnostic pop
  462. #endif
  463. public:
  464. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
  465. if (p_argument >= 0) {
  466. return call_get_argument_metadata<P...>(p_argument);
  467. } else {
  468. return GetTypeInfo<R>::METADATA;
  469. }
  470. }
  471. virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
  472. Variant ret;
  473. #ifdef TYPED_METHOD_BIND
  474. call_with_variant_args_retc_dv(static_cast<T *>(p_instance), method, p_args, (int)p_argument_count, ret, r_error, get_default_arguments());
  475. #else
  476. call_with_variant_args_retc_dv((MB_T *)p_instance, method, p_args, p_argument_count, ret, r_error, get_default_arguments());
  477. #endif
  478. return ret;
  479. }
  480. virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
  481. #ifdef TYPED_METHOD_BIND
  482. call_with_ptr_args<T, R, P...>(static_cast<T *>(p_instance), method, p_args, r_ret);
  483. #else
  484. call_with_ptr_args<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, r_ret);
  485. #endif // TYPED_METHOD_BIND
  486. }
  487. MethodBindTRC(R (MB_T::*p_method)(P...) const) {
  488. method = p_method;
  489. generate_argument_types(sizeof...(P));
  490. set_argument_count(sizeof...(P));
  491. set_return(true);
  492. }
  493. };
  494. template <class T, class R, class... P>
  495. MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
  496. #ifdef TYPED_METHOD_BIND
  497. MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method));
  498. #else
  499. MethodBind *a = memnew((MethodBindTRC<R, P...>)(reinterpret_cast<R (MB_T::*)(P...) const>(p_method)));
  500. #endif // TYPED_METHOD_BIND
  501. a->set_instance_class(T::get_class_static());
  502. return a;
  503. }
  504. // STATIC BINDS
  505. // no return
  506. template <class... P>
  507. class MethodBindTS : public MethodBind {
  508. void (*function)(P...);
  509. protected:
  510. // GCC raises warnings in the case P = {} as the comparison is always false...
  511. #if defined(__GNUC__) && !defined(__clang__)
  512. #pragma GCC diagnostic push
  513. #pragma GCC diagnostic ignored "-Wlogical-op"
  514. #endif
  515. virtual GDNativeVariantType gen_argument_type(int p_arg) const {
  516. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  517. return call_get_argument_type<P...>(p_arg);
  518. } else {
  519. return GDNATIVE_VARIANT_TYPE_NIL;
  520. }
  521. }
  522. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
  523. GDNativePropertyInfo pi;
  524. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  525. call_get_argument_type_info<P...>(p_arg, pi);
  526. } else {
  527. pi = PropertyInfo();
  528. }
  529. return pi;
  530. }
  531. #if defined(__GNUC__) && !defined(__clang__)
  532. #pragma GCC diagnostic pop
  533. #endif
  534. public:
  535. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_arg) const {
  536. return call_get_argument_metadata<P...>(p_arg);
  537. }
  538. virtual Variant call(GDExtensionClassInstancePtr p_object, const GDNativeVariantPtr *p_args, const GDNativeInt p_arg_count, GDNativeCallError &r_error) const {
  539. (void)p_object; // unused
  540. call_with_variant_args_static_dv(function, p_args, p_arg_count, r_error, get_default_arguments());
  541. return Variant();
  542. }
  543. virtual void ptrcall(GDExtensionClassInstancePtr p_object, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
  544. (void)p_object;
  545. (void)r_ret;
  546. call_with_ptr_args_static_method(function, p_args);
  547. }
  548. MethodBindTS(void (*p_function)(P...)) {
  549. function = p_function;
  550. generate_argument_types(sizeof...(P));
  551. set_argument_count(sizeof...(P));
  552. set_static(true);
  553. }
  554. };
  555. template <class... P>
  556. MethodBind *create_static_method_bind(void (*p_method)(P...)) {
  557. MethodBind *a = memnew((MethodBindTS<P...>)(p_method));
  558. return a;
  559. }
  560. // return
  561. template <class R, class... P>
  562. class MethodBindTRS : public MethodBind {
  563. R(*function)
  564. (P...);
  565. protected:
  566. // GCC raises warnings in the case P = {} as the comparison is always false...
  567. #if defined(__GNUC__) && !defined(__clang__)
  568. #pragma GCC diagnostic push
  569. #pragma GCC diagnostic ignored "-Wlogical-op"
  570. #endif
  571. virtual GDNativeVariantType gen_argument_type(int p_arg) const {
  572. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  573. return call_get_argument_type<P...>(p_arg);
  574. } else {
  575. return GDNativeVariantType(GetTypeInfo<R>::VARIANT_TYPE);
  576. }
  577. }
  578. virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
  579. if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
  580. GDNativePropertyInfo pi;
  581. call_get_argument_type_info<P...>(p_arg, pi);
  582. return pi;
  583. } else {
  584. return GetTypeInfo<R>::get_class_info();
  585. }
  586. }
  587. #if defined(__GNUC__) && !defined(__clang__)
  588. #pragma GCC diagnostic pop
  589. #endif
  590. public:
  591. virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_arg) const {
  592. if (p_arg >= 0) {
  593. return call_get_argument_metadata<P...>(p_arg);
  594. } else {
  595. return GetTypeInfo<R>::METADATA;
  596. }
  597. }
  598. virtual Variant call(GDExtensionClassInstancePtr p_object, const GDNativeVariantPtr *p_args, const GDNativeInt p_arg_count, GDNativeCallError &r_error) const {
  599. Variant ret;
  600. call_with_variant_args_static_ret_dv(function, p_args, p_arg_count, ret, r_error, get_default_arguments());
  601. return ret;
  602. }
  603. virtual void ptrcall(GDExtensionClassInstancePtr p_object, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
  604. (void)p_object;
  605. call_with_ptr_args_static_method_ret(function, p_args, r_ret);
  606. }
  607. MethodBindTRS(R (*p_function)(P...)) {
  608. function = p_function;
  609. generate_argument_types(sizeof...(P));
  610. set_argument_count(sizeof...(P));
  611. set_static(true);
  612. set_return(true);
  613. }
  614. };
  615. template <class R, class... P>
  616. MethodBind *create_static_method_bind(R (*p_method)(P...)) {
  617. MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method));
  618. return a;
  619. }
  620. } // namespace godot
  621. #endif // ! GODOT_CPP_METHOD_BIND_HPP