bindings_generator.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*************************************************************************/
  2. /* bindings_generator.h */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2019 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 BINDINGS_GENERATOR_H
  31. #define BINDINGS_GENERATOR_H
  32. #include "class_db.h"
  33. #include "editor/doc/doc_data.h"
  34. #include "editor/editor_help.h"
  35. #ifdef DEBUG_METHODS_ENABLED
  36. #include "ustring.h"
  37. class BindingsGenerator {
  38. struct ConstantInterface {
  39. String name;
  40. int value;
  41. const DocData::ConstantDoc *const_doc;
  42. ConstantInterface() {}
  43. ConstantInterface(const String &p_name, int p_value) {
  44. name = p_name;
  45. value = p_value;
  46. }
  47. };
  48. struct EnumInterface {
  49. StringName cname;
  50. String prefix;
  51. List<ConstantInterface> constants;
  52. _FORCE_INLINE_ bool operator==(const EnumInterface &p_ienum) const {
  53. return p_ienum.cname == cname;
  54. }
  55. EnumInterface() {}
  56. EnumInterface(const StringName &p_cname) {
  57. cname = p_cname;
  58. }
  59. };
  60. struct PropertyInterface {
  61. StringName cname;
  62. String proxy_name;
  63. int index;
  64. StringName setter;
  65. StringName getter;
  66. const DocData::PropertyDoc *prop_doc;
  67. };
  68. struct TypeReference {
  69. StringName cname;
  70. bool is_enum;
  71. TypeReference() {
  72. is_enum = false;
  73. }
  74. };
  75. struct ArgumentInterface {
  76. enum DefaultParamMode {
  77. CONSTANT,
  78. NULLABLE_VAL,
  79. NULLABLE_REF
  80. };
  81. TypeReference type;
  82. String name;
  83. String default_argument;
  84. DefaultParamMode def_param_mode;
  85. ArgumentInterface() {
  86. def_param_mode = CONSTANT;
  87. }
  88. };
  89. struct MethodInterface {
  90. String name;
  91. StringName cname;
  92. /**
  93. * Name of the C# method
  94. */
  95. String proxy_name;
  96. /**
  97. * [TypeInterface::name] of the return type
  98. */
  99. TypeReference return_type;
  100. /**
  101. * Determines if the method has a variable number of arguments (VarArg)
  102. */
  103. bool is_vararg;
  104. /**
  105. * Virtual methods ("virtual" as defined by the Godot API) are methods that by default do nothing,
  106. * but can be overridden by the user to add custom functionality.
  107. * e.g.: _ready, _process, etc.
  108. */
  109. bool is_virtual;
  110. /**
  111. * Determines if the call should fallback to Godot's object.Call(string, params) in C#.
  112. */
  113. bool requires_object_call;
  114. /**
  115. * Determines if the method visibility is `internal` (visible only to files in the same assembly).
  116. * Currently, we only use this for methods that are not meant to be exposed,
  117. * but are required by properties as getters or setters.
  118. * Methods that are not meant to be exposed are those that begin with underscore and are not virtual.
  119. */
  120. bool is_internal;
  121. List<ArgumentInterface> arguments;
  122. const DocData::MethodDoc *method_doc;
  123. void add_argument(const ArgumentInterface &argument) {
  124. arguments.push_back(argument);
  125. }
  126. MethodInterface() {
  127. return_type.cname = BindingsGenerator::get_singleton()->name_cache.type_void;
  128. is_vararg = false;
  129. is_virtual = false;
  130. requires_object_call = false;
  131. is_internal = false;
  132. method_doc = NULL;
  133. }
  134. };
  135. struct TypeInterface {
  136. /**
  137. * Identifier name for this type.
  138. * Also used to format [c_out].
  139. */
  140. String name;
  141. StringName cname;
  142. /**
  143. * Identifier name of the base class.
  144. */
  145. StringName base_name;
  146. /**
  147. * Name of the C# class
  148. */
  149. String proxy_name;
  150. ClassDB::APIType api_type;
  151. bool is_enum;
  152. bool is_object_type;
  153. bool is_singleton;
  154. bool is_reference;
  155. /**
  156. * Used only by Object-derived types.
  157. * Determines if this type is not virtual (incomplete).
  158. * e.g.: CanvasItem cannot be instantiated.
  159. */
  160. bool is_instantiable;
  161. /**
  162. * Used only by Object-derived types.
  163. * Determines if the C# class owns the native handle and must free it somehow when disposed.
  164. * e.g.: Reference types must notify when the C# instance is disposed, for proper refcounting.
  165. */
  166. bool memory_own;
  167. /**
  168. * Determines if the file must have a using directive for System.Collections.Generic
  169. * e.g.: When the generated class makes use of Dictionary
  170. */
  171. bool requires_collections;
  172. // !! The comments of the following fields make reference to other fields via square brackets, e.g.: [field_name]
  173. // !! When renaming those fields, make sure to rename their references in the comments
  174. // --- C INTERFACE ---
  175. static const char *DEFAULT_VARARG_C_IN;
  176. /**
  177. * One or more statements that manipulate the parameter before being passed as argument of a ptrcall.
  178. * If the statement adds a local that must be passed as the argument instead of the parameter,
  179. * the name of that local must be specified with [c_arg_in].
  180. * For variadic methods, this field is required and, if empty, [DEFAULT_VARARG_C_IN] is used instead.
  181. * Formatting elements:
  182. * %0: [c_type] of the parameter
  183. * %1: name of the parameter
  184. */
  185. String c_in;
  186. /**
  187. * Determines the name of the variable that will be passed as argument to a ptrcall.
  188. * By default the value equals the name of the parameter,
  189. * this varies for types that require special manipulation via [c_in].
  190. * Formatting elements:
  191. * %0 or %s: name of the parameter
  192. */
  193. String c_arg_in;
  194. /**
  195. * One or more statements that determine how a variable of this type is returned from a function.
  196. * It must contain the return statement(s).
  197. * Formatting elements:
  198. * %0: [c_type_out] of the return type
  199. * %1: name of the variable to be returned
  200. * %2: [name] of the return type
  201. */
  202. String c_out;
  203. /**
  204. * The actual expected type, as seen (in most cases) in Variant copy constructors
  205. * Used for the type of the return variable and to format [c_in].
  206. * The value must be the following depending of the type:
  207. * Object-derived types: Object*
  208. * Other types: [name]
  209. * -- Exceptions --
  210. * VarArg (fictitious type to represent variable arguments): Array
  211. * float: double (because ptrcall only supports double)
  212. * int: int64_t (because ptrcall only supports int64_t and uint64_t)
  213. * Reference types override this for the type of the return variable: Ref<Reference>
  214. */
  215. String c_type;
  216. /**
  217. * Determines the type used for parameters in function signatures.
  218. */
  219. String c_type_in;
  220. /**
  221. * Determines the return type used for function signatures.
  222. * Also used to construct a default value to return in case of errors,
  223. * and to format [c_out].
  224. */
  225. String c_type_out;
  226. // --- C# INTERFACE ---
  227. /**
  228. * An expression that overrides the way the parameter is passed to the internal call.
  229. * If empty, the parameter is passed as is.
  230. * Formatting elements:
  231. * %0 or %s: name of the parameter
  232. */
  233. String cs_in;
  234. /**
  235. * One or more statements that determine how a variable of this type is returned from a method.
  236. * It must contain the return statement(s).
  237. * Formatting elements:
  238. * %0: internal method call statement
  239. * %1: [cs_type] of the return type
  240. * %2: [im_type_out] of the return type
  241. */
  242. String cs_out;
  243. /**
  244. * Type used for method signatures, both for parameters and the return type.
  245. * Same as [proxy_name] except for variable arguments (VarArg).
  246. */
  247. String cs_type;
  248. /**
  249. * Type used for parameters of internal call methods.
  250. */
  251. String im_type_in;
  252. /**
  253. * Type used for the return type of internal call methods.
  254. */
  255. String im_type_out;
  256. const DocData::ClassDoc *class_doc;
  257. List<ConstantInterface> constants;
  258. List<EnumInterface> enums;
  259. List<PropertyInterface> properties;
  260. List<MethodInterface> methods;
  261. const MethodInterface *find_method_by_name(const StringName &p_cname) const {
  262. for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) {
  263. if (E->get().cname == p_cname)
  264. return &E->get();
  265. }
  266. return NULL;
  267. }
  268. const PropertyInterface *find_property_by_proxy_name(const String &p_proxy_name) const {
  269. for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) {
  270. if (E->get().proxy_name == p_proxy_name)
  271. return &E->get();
  272. }
  273. return NULL;
  274. }
  275. private:
  276. static void _init_value_type(TypeInterface &itype) {
  277. itype.proxy_name = itype.name;
  278. itype.c_type = itype.name;
  279. itype.c_type_in = "void*";
  280. itype.c_type_out = "MonoObject*";
  281. itype.cs_type = itype.proxy_name;
  282. itype.im_type_in = "ref " + itype.proxy_name;
  283. itype.im_type_out = itype.proxy_name;
  284. itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
  285. }
  286. public:
  287. static TypeInterface create_value_type(const String &p_name) {
  288. TypeInterface itype;
  289. itype.name = p_name;
  290. itype.cname = StringName(p_name);
  291. _init_value_type(itype);
  292. return itype;
  293. }
  294. static TypeInterface create_value_type(const StringName &p_name) {
  295. TypeInterface itype;
  296. itype.name = p_name.operator String();
  297. itype.cname = p_name;
  298. _init_value_type(itype);
  299. return itype;
  300. }
  301. static TypeInterface create_object_type(const StringName &p_cname, ClassDB::APIType p_api_type) {
  302. TypeInterface itype;
  303. itype.name = p_cname;
  304. itype.cname = p_cname;
  305. itype.proxy_name = itype.name.begins_with("_") ? itype.name.substr(1, itype.name.length()) : itype.name;
  306. itype.api_type = p_api_type;
  307. itype.is_object_type = true;
  308. itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
  309. return itype;
  310. }
  311. static void create_placeholder_type(TypeInterface &r_itype, const StringName &p_cname) {
  312. r_itype.name = p_cname;
  313. r_itype.cname = p_cname;
  314. r_itype.proxy_name = r_itype.name;
  315. r_itype.c_type = r_itype.name;
  316. r_itype.c_type_in = "MonoObject*";
  317. r_itype.c_type_out = "MonoObject*";
  318. r_itype.cs_type = r_itype.proxy_name;
  319. r_itype.im_type_in = r_itype.proxy_name;
  320. r_itype.im_type_out = r_itype.proxy_name;
  321. }
  322. static void postsetup_enum_type(TypeInterface &r_enum_itype) {
  323. r_enum_itype.c_arg_in = "&%s";
  324. r_enum_itype.c_type = "int";
  325. r_enum_itype.c_type_in = "int";
  326. r_enum_itype.c_type_out = "int";
  327. r_enum_itype.cs_type = r_enum_itype.proxy_name;
  328. r_enum_itype.cs_in = "(int)%s";
  329. r_enum_itype.cs_out = "return (%1)%0;";
  330. r_enum_itype.im_type_in = "int";
  331. r_enum_itype.im_type_out = "int";
  332. r_enum_itype.class_doc = &EditorHelp::get_doc_data()->class_list[r_enum_itype.proxy_name];
  333. }
  334. TypeInterface() {
  335. api_type = ClassDB::API_NONE;
  336. is_enum = false;
  337. is_object_type = false;
  338. is_singleton = false;
  339. is_reference = false;
  340. is_instantiable = false;
  341. memory_own = false;
  342. requires_collections = false;
  343. c_arg_in = "%s";
  344. class_doc = NULL;
  345. }
  346. };
  347. struct InternalCall {
  348. String name;
  349. String im_type_out; // Return type for the C# method declaration. Also used as companion of [unique_siq]
  350. String im_sig; // Signature for the C# method declaration
  351. String unique_sig; // Unique signature to avoid duplicates in containers
  352. bool editor_only;
  353. InternalCall() {}
  354. InternalCall(const String &p_name, const String &p_im_type_out, const String &p_im_sig = String(), const String &p_unique_sig = String()) {
  355. name = p_name;
  356. im_type_out = p_im_type_out;
  357. im_sig = p_im_sig;
  358. unique_sig = p_unique_sig;
  359. editor_only = false;
  360. }
  361. InternalCall(ClassDB::APIType api_type, const String &p_name, const String &p_im_type_out, const String &p_im_sig = String(), const String &p_unique_sig = String()) {
  362. name = p_name;
  363. im_type_out = p_im_type_out;
  364. im_sig = p_im_sig;
  365. unique_sig = p_unique_sig;
  366. editor_only = api_type == ClassDB::API_EDITOR;
  367. }
  368. inline bool operator==(const InternalCall &p_a) const {
  369. return p_a.unique_sig == unique_sig;
  370. }
  371. };
  372. static bool verbose_output;
  373. OrderedHashMap<StringName, TypeInterface> obj_types;
  374. Map<StringName, TypeInterface> placeholder_types;
  375. Map<StringName, TypeInterface> builtin_types;
  376. Map<StringName, TypeInterface> enum_types;
  377. List<EnumInterface> global_enums;
  378. List<ConstantInterface> global_constants;
  379. Map<StringName, String> extra_members;
  380. List<InternalCall> method_icalls;
  381. List<InternalCall> builtin_method_icalls;
  382. Map<const MethodInterface *, const InternalCall *> method_icalls_map;
  383. List<const InternalCall *> generated_icall_funcs;
  384. List<InternalCall> core_custom_icalls;
  385. List<InternalCall> editor_custom_icalls;
  386. struct NameCache {
  387. StringName type_void;
  388. StringName type_int;
  389. StringName type_Array;
  390. StringName type_Dictionary;
  391. StringName type_Variant;
  392. StringName type_VarArg;
  393. StringName type_Object;
  394. StringName type_Reference;
  395. StringName enum_Error;
  396. NameCache() {
  397. type_void = StaticCString::create("void");
  398. type_int = StaticCString::create("int");
  399. type_Array = StaticCString::create("Array");
  400. type_Dictionary = StaticCString::create("Dictionary");
  401. type_Variant = StaticCString::create("Variant");
  402. type_VarArg = StaticCString::create("VarArg");
  403. type_Object = StaticCString::create("Object");
  404. type_Reference = StaticCString::create("Reference");
  405. enum_Error = StaticCString::create("Error");
  406. }
  407. NameCache(const NameCache &);
  408. NameCache &operator=(const NameCache &);
  409. };
  410. NameCache name_cache;
  411. const List<InternalCall>::Element *find_icall_by_name(const String &p_name, const List<InternalCall> &p_list) {
  412. const List<InternalCall>::Element *it = p_list.front();
  413. while (it) {
  414. if (it->get().name == p_name) return it;
  415. it = it->next();
  416. }
  417. return NULL;
  418. }
  419. inline String get_unique_sig(const TypeInterface &p_type) {
  420. if (p_type.is_reference)
  421. return "Ref";
  422. else if (p_type.is_object_type)
  423. return "Obj";
  424. else if (p_type.is_enum)
  425. return "int";
  426. return p_type.name;
  427. }
  428. String _determine_enum_prefix(const EnumInterface &p_ienum);
  429. void _generate_header_icalls();
  430. void _generate_method_icalls(const TypeInterface &p_itype);
  431. const TypeInterface *_get_type_or_null(const TypeReference &p_typeref);
  432. const TypeInterface *_get_type_or_placeholder(const TypeReference &p_typeref);
  433. void _default_argument_from_variant(const Variant &p_val, ArgumentInterface &r_iarg);
  434. void _populate_builtin_type(TypeInterface &r_itype, Variant::Type vtype);
  435. void _populate_object_type_interfaces();
  436. void _populate_builtin_type_interfaces();
  437. void _populate_global_constants();
  438. Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file);
  439. Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_iprop, List<String> &p_output);
  440. Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, List<String> &p_output);
  441. void _generate_global_constants(List<String> &p_output);
  442. Error _generate_glue_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, List<String> &p_output);
  443. Error _save_file(const String &p_path, const List<String> &p_content);
  444. BindingsGenerator() {}
  445. BindingsGenerator(const BindingsGenerator &);
  446. BindingsGenerator &operator=(const BindingsGenerator &);
  447. friend class CSharpLanguage;
  448. static BindingsGenerator *singleton;
  449. public:
  450. Error generate_cs_core_project(const String &p_output_dir, bool p_verbose_output = true);
  451. Error generate_cs_editor_project(const String &p_output_dir, const String &p_core_dll_path, bool p_verbose_output = true);
  452. Error generate_glue(const String &p_output_dir);
  453. static uint32_t get_version();
  454. static uint32_t get_cs_glue_version();
  455. void initialize();
  456. _FORCE_INLINE_ static BindingsGenerator *get_singleton() {
  457. if (!singleton) {
  458. singleton = memnew(BindingsGenerator);
  459. singleton->initialize();
  460. }
  461. return singleton;
  462. }
  463. static void handle_cmdline_args(const List<String> &p_cmdline_args);
  464. };
  465. #endif
  466. #endif // BINDINGS_GENERATOR_H