123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- /*************************************************************************/
- /* bindings_generator.h */
- /*************************************************************************/
- /* This file is part of: */
- /* GODOT ENGINE */
- /* https://godotengine.org */
- /*************************************************************************/
- /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
- /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
- /* */
- /* Permission is hereby granted, free of charge, to any person obtaining */
- /* a copy of this software and associated documentation files (the */
- /* "Software"), to deal in the Software without restriction, including */
- /* without limitation the rights to use, copy, modify, merge, publish, */
- /* distribute, sublicense, and/or sell copies of the Software, and to */
- /* permit persons to whom the Software is furnished to do so, subject to */
- /* the following conditions: */
- /* */
- /* The above copyright notice and this permission notice shall be */
- /* included in all copies or substantial portions of the Software. */
- /* */
- /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
- /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
- /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
- /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
- /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
- /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
- /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
- /*************************************************************************/
- #ifndef BINDINGS_GENERATOR_H
- #define BINDINGS_GENERATOR_H
- #include "class_db.h"
- #include "editor/doc/doc_data.h"
- #include "editor/editor_help.h"
- #ifdef DEBUG_METHODS_ENABLED
- #include "ustring.h"
- class BindingsGenerator {
- struct ConstantInterface {
- String name;
- int value;
- const DocData::ConstantDoc *const_doc;
- ConstantInterface() {}
- ConstantInterface(const String &p_name, int p_value) {
- name = p_name;
- value = p_value;
- }
- };
- struct EnumInterface {
- StringName cname;
- String prefix;
- List<ConstantInterface> constants;
- _FORCE_INLINE_ bool operator==(const EnumInterface &p_ienum) const {
- return p_ienum.cname == cname;
- }
- EnumInterface() {}
- EnumInterface(const StringName &p_cname) {
- cname = p_cname;
- }
- };
- struct PropertyInterface {
- StringName cname;
- String proxy_name;
- int index;
- StringName setter;
- StringName getter;
- const DocData::PropertyDoc *prop_doc;
- };
- struct TypeReference {
- StringName cname;
- bool is_enum;
- TypeReference() {
- is_enum = false;
- }
- };
- struct ArgumentInterface {
- enum DefaultParamMode {
- CONSTANT,
- NULLABLE_VAL,
- NULLABLE_REF
- };
- TypeReference type;
- String name;
- String default_argument;
- DefaultParamMode def_param_mode;
- ArgumentInterface() {
- def_param_mode = CONSTANT;
- }
- };
- struct MethodInterface {
- String name;
- StringName cname;
- /**
- * Name of the C# method
- */
- String proxy_name;
- /**
- * [TypeInterface::name] of the return type
- */
- TypeReference return_type;
- /**
- * Determines if the method has a variable number of arguments (VarArg)
- */
- bool is_vararg;
- /**
- * Virtual methods ("virtual" as defined by the Godot API) are methods that by default do nothing,
- * but can be overridden by the user to add custom functionality.
- * e.g.: _ready, _process, etc.
- */
- bool is_virtual;
- /**
- * Determines if the call should fallback to Godot's object.Call(string, params) in C#.
- */
- bool requires_object_call;
- /**
- * Determines if the method visibility is `internal` (visible only to files in the same assembly).
- * Currently, we only use this for methods that are not meant to be exposed,
- * but are required by properties as getters or setters.
- * Methods that are not meant to be exposed are those that begin with underscore and are not virtual.
- */
- bool is_internal;
- List<ArgumentInterface> arguments;
- const DocData::MethodDoc *method_doc;
- void add_argument(const ArgumentInterface &argument) {
- arguments.push_back(argument);
- }
- MethodInterface() {
- return_type.cname = BindingsGenerator::get_singleton()->name_cache.type_void;
- is_vararg = false;
- is_virtual = false;
- requires_object_call = false;
- is_internal = false;
- method_doc = NULL;
- }
- };
- struct TypeInterface {
- /**
- * Identifier name for this type.
- * Also used to format [c_out].
- */
- String name;
- StringName cname;
- /**
- * Identifier name of the base class.
- */
- StringName base_name;
- /**
- * Name of the C# class
- */
- String proxy_name;
- ClassDB::APIType api_type;
- bool is_enum;
- bool is_object_type;
- bool is_singleton;
- bool is_reference;
- /**
- * Used only by Object-derived types.
- * Determines if this type is not virtual (incomplete).
- * e.g.: CanvasItem cannot be instantiated.
- */
- bool is_instantiable;
- /**
- * Used only by Object-derived types.
- * Determines if the C# class owns the native handle and must free it somehow when disposed.
- * e.g.: Reference types must notify when the C# instance is disposed, for proper refcounting.
- */
- bool memory_own;
- /**
- * Determines if the file must have a using directive for System.Collections.Generic
- * e.g.: When the generated class makes use of Dictionary
- */
- bool requires_collections;
- // !! The comments of the following fields make reference to other fields via square brackets, e.g.: [field_name]
- // !! When renaming those fields, make sure to rename their references in the comments
- // --- C INTERFACE ---
- static const char *DEFAULT_VARARG_C_IN;
- /**
- * One or more statements that manipulate the parameter before being passed as argument of a ptrcall.
- * If the statement adds a local that must be passed as the argument instead of the parameter,
- * the name of that local must be specified with [c_arg_in].
- * For variadic methods, this field is required and, if empty, [DEFAULT_VARARG_C_IN] is used instead.
- * Formatting elements:
- * %0: [c_type] of the parameter
- * %1: name of the parameter
- */
- String c_in;
- /**
- * Determines the name of the variable that will be passed as argument to a ptrcall.
- * By default the value equals the name of the parameter,
- * this varies for types that require special manipulation via [c_in].
- * Formatting elements:
- * %0 or %s: name of the parameter
- */
- String c_arg_in;
- /**
- * One or more statements that determine how a variable of this type is returned from a function.
- * It must contain the return statement(s).
- * Formatting elements:
- * %0: [c_type_out] of the return type
- * %1: name of the variable to be returned
- * %2: [name] of the return type
- */
- String c_out;
- /**
- * The actual expected type, as seen (in most cases) in Variant copy constructors
- * Used for the type of the return variable and to format [c_in].
- * The value must be the following depending of the type:
- * Object-derived types: Object*
- * Other types: [name]
- * -- Exceptions --
- * VarArg (fictitious type to represent variable arguments): Array
- * float: double (because ptrcall only supports double)
- * int: int64_t (because ptrcall only supports int64_t and uint64_t)
- * Reference types override this for the type of the return variable: Ref<Reference>
- */
- String c_type;
- /**
- * Determines the type used for parameters in function signatures.
- */
- String c_type_in;
- /**
- * Determines the return type used for function signatures.
- * Also used to construct a default value to return in case of errors,
- * and to format [c_out].
- */
- String c_type_out;
- // --- C# INTERFACE ---
- /**
- * An expression that overrides the way the parameter is passed to the internal call.
- * If empty, the parameter is passed as is.
- * Formatting elements:
- * %0 or %s: name of the parameter
- */
- String cs_in;
- /**
- * One or more statements that determine how a variable of this type is returned from a method.
- * It must contain the return statement(s).
- * Formatting elements:
- * %0: internal method call statement
- * %1: [cs_type] of the return type
- * %2: [im_type_out] of the return type
- */
- String cs_out;
- /**
- * Type used for method signatures, both for parameters and the return type.
- * Same as [proxy_name] except for variable arguments (VarArg).
- */
- String cs_type;
- /**
- * Type used for parameters of internal call methods.
- */
- String im_type_in;
- /**
- * Type used for the return type of internal call methods.
- */
- String im_type_out;
- const DocData::ClassDoc *class_doc;
- List<ConstantInterface> constants;
- List<EnumInterface> enums;
- List<PropertyInterface> properties;
- List<MethodInterface> methods;
- const MethodInterface *find_method_by_name(const StringName &p_cname) const {
- for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().cname == p_cname)
- return &E->get();
- }
- return NULL;
- }
- const PropertyInterface *find_property_by_proxy_name(const String &p_proxy_name) const {
- for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) {
- if (E->get().proxy_name == p_proxy_name)
- return &E->get();
- }
- return NULL;
- }
- private:
- static void _init_value_type(TypeInterface &itype) {
- itype.proxy_name = itype.name;
- itype.c_type = itype.name;
- itype.c_type_in = "void*";
- itype.c_type_out = "MonoObject*";
- itype.cs_type = itype.proxy_name;
- itype.im_type_in = "ref " + itype.proxy_name;
- itype.im_type_out = itype.proxy_name;
- itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
- }
- public:
- static TypeInterface create_value_type(const String &p_name) {
- TypeInterface itype;
- itype.name = p_name;
- itype.cname = StringName(p_name);
- _init_value_type(itype);
- return itype;
- }
- static TypeInterface create_value_type(const StringName &p_name) {
- TypeInterface itype;
- itype.name = p_name.operator String();
- itype.cname = p_name;
- _init_value_type(itype);
- return itype;
- }
- static TypeInterface create_object_type(const StringName &p_cname, ClassDB::APIType p_api_type) {
- TypeInterface itype;
- itype.name = p_cname;
- itype.cname = p_cname;
- itype.proxy_name = itype.name.begins_with("_") ? itype.name.substr(1, itype.name.length()) : itype.name;
- itype.api_type = p_api_type;
- itype.is_object_type = true;
- itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
- return itype;
- }
- static void create_placeholder_type(TypeInterface &r_itype, const StringName &p_cname) {
- r_itype.name = p_cname;
- r_itype.cname = p_cname;
- r_itype.proxy_name = r_itype.name;
- r_itype.c_type = r_itype.name;
- r_itype.c_type_in = "MonoObject*";
- r_itype.c_type_out = "MonoObject*";
- r_itype.cs_type = r_itype.proxy_name;
- r_itype.im_type_in = r_itype.proxy_name;
- r_itype.im_type_out = r_itype.proxy_name;
- }
- static void postsetup_enum_type(TypeInterface &r_enum_itype) {
- r_enum_itype.c_arg_in = "&%s";
- r_enum_itype.c_type = "int";
- r_enum_itype.c_type_in = "int";
- r_enum_itype.c_type_out = "int";
- r_enum_itype.cs_type = r_enum_itype.proxy_name;
- r_enum_itype.cs_in = "(int)%s";
- r_enum_itype.cs_out = "return (%1)%0;";
- r_enum_itype.im_type_in = "int";
- r_enum_itype.im_type_out = "int";
- r_enum_itype.class_doc = &EditorHelp::get_doc_data()->class_list[r_enum_itype.proxy_name];
- }
- TypeInterface() {
- api_type = ClassDB::API_NONE;
- is_enum = false;
- is_object_type = false;
- is_singleton = false;
- is_reference = false;
- is_instantiable = false;
- memory_own = false;
- requires_collections = false;
- c_arg_in = "%s";
- class_doc = NULL;
- }
- };
- struct InternalCall {
- String name;
- String im_type_out; // Return type for the C# method declaration. Also used as companion of [unique_siq]
- String im_sig; // Signature for the C# method declaration
- String unique_sig; // Unique signature to avoid duplicates in containers
- bool editor_only;
- InternalCall() {}
- InternalCall(const String &p_name, const String &p_im_type_out, const String &p_im_sig = String(), const String &p_unique_sig = String()) {
- name = p_name;
- im_type_out = p_im_type_out;
- im_sig = p_im_sig;
- unique_sig = p_unique_sig;
- editor_only = false;
- }
- 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()) {
- name = p_name;
- im_type_out = p_im_type_out;
- im_sig = p_im_sig;
- unique_sig = p_unique_sig;
- editor_only = api_type == ClassDB::API_EDITOR;
- }
- inline bool operator==(const InternalCall &p_a) const {
- return p_a.unique_sig == unique_sig;
- }
- };
- static bool verbose_output;
- OrderedHashMap<StringName, TypeInterface> obj_types;
- Map<StringName, TypeInterface> placeholder_types;
- Map<StringName, TypeInterface> builtin_types;
- Map<StringName, TypeInterface> enum_types;
- List<EnumInterface> global_enums;
- List<ConstantInterface> global_constants;
- Map<StringName, String> extra_members;
- List<InternalCall> method_icalls;
- List<InternalCall> builtin_method_icalls;
- Map<const MethodInterface *, const InternalCall *> method_icalls_map;
- List<const InternalCall *> generated_icall_funcs;
- List<InternalCall> core_custom_icalls;
- List<InternalCall> editor_custom_icalls;
- struct NameCache {
- StringName type_void;
- StringName type_int;
- StringName type_Array;
- StringName type_Dictionary;
- StringName type_Variant;
- StringName type_VarArg;
- StringName type_Object;
- StringName type_Reference;
- StringName enum_Error;
- NameCache() {
- type_void = StaticCString::create("void");
- type_int = StaticCString::create("int");
- type_Array = StaticCString::create("Array");
- type_Dictionary = StaticCString::create("Dictionary");
- type_Variant = StaticCString::create("Variant");
- type_VarArg = StaticCString::create("VarArg");
- type_Object = StaticCString::create("Object");
- type_Reference = StaticCString::create("Reference");
- enum_Error = StaticCString::create("Error");
- }
- NameCache(const NameCache &);
- NameCache &operator=(const NameCache &);
- };
- NameCache name_cache;
- const List<InternalCall>::Element *find_icall_by_name(const String &p_name, const List<InternalCall> &p_list) {
- const List<InternalCall>::Element *it = p_list.front();
- while (it) {
- if (it->get().name == p_name) return it;
- it = it->next();
- }
- return NULL;
- }
- inline String get_unique_sig(const TypeInterface &p_type) {
- if (p_type.is_reference)
- return "Ref";
- else if (p_type.is_object_type)
- return "Obj";
- else if (p_type.is_enum)
- return "int";
- return p_type.name;
- }
- String _determine_enum_prefix(const EnumInterface &p_ienum);
- void _generate_header_icalls();
- void _generate_method_icalls(const TypeInterface &p_itype);
- const TypeInterface *_get_type_or_null(const TypeReference &p_typeref);
- const TypeInterface *_get_type_or_placeholder(const TypeReference &p_typeref);
- void _default_argument_from_variant(const Variant &p_val, ArgumentInterface &r_iarg);
- void _populate_builtin_type(TypeInterface &r_itype, Variant::Type vtype);
- void _populate_object_type_interfaces();
- void _populate_builtin_type_interfaces();
- void _populate_global_constants();
- Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file);
- Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_iprop, List<String> &p_output);
- Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, List<String> &p_output);
- void _generate_global_constants(List<String> &p_output);
- Error _generate_glue_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, List<String> &p_output);
- Error _save_file(const String &p_path, const List<String> &p_content);
- BindingsGenerator() {}
- BindingsGenerator(const BindingsGenerator &);
- BindingsGenerator &operator=(const BindingsGenerator &);
- friend class CSharpLanguage;
- static BindingsGenerator *singleton;
- public:
- Error generate_cs_core_project(const String &p_output_dir, bool p_verbose_output = true);
- Error generate_cs_editor_project(const String &p_output_dir, const String &p_core_dll_path, bool p_verbose_output = true);
- Error generate_glue(const String &p_output_dir);
- static uint32_t get_version();
- static uint32_t get_cs_glue_version();
- void initialize();
- _FORCE_INLINE_ static BindingsGenerator *get_singleton() {
- if (!singleton) {
- singleton = memnew(BindingsGenerator);
- singleton->initialize();
- }
- return singleton;
- }
- static void handle_cmdline_args(const List<String> &p_cmdline_args);
- };
- #endif
- #endif // BINDINGS_GENERATOR_H
|