From 58448561c77db9a70cf25b70a0f715b570be99e7 Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Thu, 25 Jan 2018 23:44:37 +0100 Subject: [PATCH] Mono: Fix NodePath and RID bindings --- modules/mono/editor/bindings_generator.cpp | 114 +++++++++++++-------- modules/mono/editor/bindings_generator.h | 1 + modules/mono/glue/builtin_types_glue.h | 59 +++++++++++ modules/mono/glue/glue_header.h | 18 ++-- 4 files changed, 145 insertions(+), 47 deletions(-) create mode 100644 modules/mono/glue/builtin_types_glue.h diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 9bf81b52bb2..37fe52c1d68 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -250,8 +250,15 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) { const TypeInterface *return_type = _get_type_by_name_or_placeholder(imethod.return_type); - String im_sig = "IntPtr " CS_PARAM_METHODBIND ", IntPtr " CS_PARAM_INSTANCE; - String im_unique_sig = imethod.return_type.operator String() + ",IntPtr,IntPtr"; + String im_sig; + String im_unique_sig; + + if (p_itype.is_object_type) { + im_sig += "IntPtr " CS_PARAM_METHODBIND ", "; + im_unique_sig += imethod.return_type.operator String() + ",IntPtr,IntPtr"; + } + + im_sig += "IntPtr " CS_PARAM_INSTANCE; // Get arguments information int i = 0; @@ -263,25 +270,37 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) { im_sig += " arg"; im_sig += itos(i + 1); - im_unique_sig += ","; - im_unique_sig += get_unique_sig(*arg_type); + if (p_itype.is_object_type) { + im_unique_sig += ","; + im_unique_sig += get_unique_sig(*arg_type); + } i++; } - // godot_icall_{argc}_{icallcount} - String icall_method = ICALL_PREFIX + itos(imethod.arguments.size()) + "_" + itos(method_icalls.size()); + String icall_method = ICALL_PREFIX; + + if (p_itype.is_object_type) { + icall_method += itos(imethod.arguments.size()) + "_" + itos(method_icalls.size()); // godot_icall_{argc}_{icallcount} + } else { + icall_method += p_itype.name + "_" + imethod.name; // godot_icall_{Type}_{method} + } InternalCall im_icall = InternalCall(p_itype.api_type, icall_method, return_type->im_type_out, im_sig, im_unique_sig); - List::Element *match = method_icalls.find(im_icall); + if (p_itype.is_object_type) { + List::Element *match = method_icalls.find(im_icall); - if (match) { - if (p_itype.api_type != ClassDB::API_EDITOR) - match->get().editor_only = false; - method_icalls_map.insert(&E->get(), &match->get()); + if (match) { + if (p_itype.api_type != ClassDB::API_EDITOR) + match->get().editor_only = false; + method_icalls_map.insert(&E->get(), &match->get()); + } else { + List::Element *added = method_icalls.push_back(im_icall); + method_icalls_map.insert(&E->get(), &added->get()); + } } else { - List::Element *added = method_icalls.push_back(im_icall); + List::Element *added = builtin_method_icalls.push_back(im_icall); method_icalls_map.insert(&E->get(), &added->get()); } } @@ -525,6 +544,8 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo ADD_INTERNAL_CALL(E->get()); for (const List::Element *E = method_icalls.front(); E; E = E->next()) ADD_INTERNAL_CALL(E->get()); + for (const List::Element *E = builtin_method_icalls.front(); E; E = E->next()) + ADD_INTERNAL_CALL(E->get()); #undef ADD_INTERNAL_CALL @@ -616,6 +637,8 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \ } + // No need to add builtin_method_icalls. Builtin types are core only + for (const List::Element *E = editor_custom_icalls.front(); E; E = E->next()) ADD_INTERNAL_CALL(E->get()); for (const List::Element *E = method_icalls.front(); E; E = E->next()) @@ -694,9 +717,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.push_back(itype.is_singleton ? "static class " : "class "); output.push_back(itype.proxy_name); - if (itype.is_singleton || !itype.is_object_type) { + if (itype.is_singleton) { output.push_back("\n"); - } else if (!is_derived_type) { + } else if (!is_derived_type || !itype.is_object_type /* assuming only object types inherit */) { output.push_back(" : IDisposable\n"); } else if (obj_types.has(itype.base_name)) { output.push_back(" : "); @@ -838,7 +861,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2); // Add the virtual Dispose - output.push_back(MEMBER_BEGIN "public virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2 + output.push_back(MEMBER_BEGIN "protected virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2 "if (disposed) return;\n" INDENT3 "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3 "NativeCalls.godot_icall_"); output.push_back(itype.proxy_name); @@ -929,7 +952,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2); // Add the virtual Dispose - output.push_back(MEMBER_BEGIN "public virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2 + output.push_back(MEMBER_BEGIN "protected virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2 "if (disposed) return;\n" INDENT3 "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3 "if (" CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L4 CS_FIELD_MEMORYOWN @@ -1122,10 +1145,14 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf String method_bind_field = "method_bind_" + itos(p_method_bind_count); - String icall_params = method_bind_field + ", " + sformat(p_itype.cs_in, "this"); String arguments_sig; String cs_in_statements; + String icall_params; + if (p_itype.is_object_type) + icall_params += method_bind_field + ", "; + icall_params += sformat(p_itype.cs_in, "this"); + List default_args_doc; // Retrieve information from the arguments @@ -1200,7 +1227,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf // Generate method { - if (!p_imethod.is_virtual && !p_imethod.requires_object_call) { + if (p_itype.is_object_type && !p_imethod.is_virtual && !p_imethod.requires_object_call) { p_output.push_back(MEMBER_BEGIN "private "); p_output.push_back(p_itype.is_singleton ? "static IntPtr " : "IntPtr "); p_output.push_back(method_bind_field + " = " CS_CLASS_NATIVECALLS "." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \""); @@ -1381,6 +1408,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { output.push_back(itos(GDMono::get_singleton()->get_api_editor_hash()) + "; }\n#endif // TOOLS_ENABLED\n"); output.push_back("void register_generated_icalls() " OPEN_BLOCK); + output.push_back("\tgodot_register_header_icalls();"); #define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \ { \ @@ -1443,6 +1471,9 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { output.push_back("#endif\n"); } + for (const List::Element *E = builtin_method_icalls.front(); E; E = E->next()) + ADD_INTERNAL_CALL_REGISTRATION(E->get()); + #undef ADD_INTERNAL_CALL_REGISTRATION output.push_back(CLOSE_BLOCK "}\n"); @@ -1518,6 +1549,9 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte i++; } + if (!p_itype.is_object_type) + return OK; // no auto-generated icall functions for builtin types + const Map::Element *match = method_icalls_map.find(&p_imethod); ERR_FAIL_NULL_V(match, ERR_BUG); @@ -2113,35 +2147,33 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { #undef INSERT_STRUCT_TYPE -#define INSERT_PRIMITIVE_TYPE(m_type) \ - { \ - itype = TypeInterface::create_value_type(String(#m_type)); \ - itype.c_arg_in = "&%s"; \ - itype.c_type_in = #m_type; \ - itype.c_type_out = #m_type; \ - itype.im_type_in = #m_type; \ - itype.im_type_out = #m_type; \ - builtin_types.insert(itype.cname, itype); \ - } - - INSERT_PRIMITIVE_TYPE(bool) - //INSERT_PRIMITIVE_TYPE(int) - - // int - itype = TypeInterface::create_value_type(String("int")); - itype.c_arg_in = "&%s_in"; - //* ptrcall only supports int64_t and uint64_t + // bool + itype = TypeInterface::create_value_type(String("bool")); + itype.c_arg_in = "&%s"; + // /* MonoBoolean <---> bool itype.c_in = "\t%0 %1_in = (%0)%1;\n"; itype.c_out = "\treturn (%0)%1;\n"; - itype.c_type = "int64_t"; - //*/ - itype.c_type_in = itype.name; - itype.c_type_out = itype.name; + itype.c_type = "bool"; + // */ + itype.c_type_in = "MonoBoolean"; + itype.c_type_out = itype.c_type_in; itype.im_type_in = itype.name; itype.im_type_out = itype.name; builtin_types.insert(itype.cname, itype); -#undef INSERT_PRIMITIVE_TYPE + // int + itype = TypeInterface::create_value_type(String("int")); + itype.c_arg_in = "&%s_in"; + // /* ptrcall only supports int64_t and uint64_t + itype.c_in = "\t%0 %1_in = (%0)%1;\n"; + itype.c_out = "\treturn (%0)%1;\n"; + itype.c_type = "int64_t"; + // */ + itype.c_type_in = "int32_t"; + itype.c_type_out = itype.c_type_in; + itype.im_type_in = itype.name; + itype.im_type_out = itype.name; + builtin_types.insert(itype.cname, itype); // real_t itype = TypeInterface(); diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 8929b45cce6..4ab8d86cf3f 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -441,6 +441,7 @@ class BindingsGenerator { Map extra_members; List method_icalls; + List builtin_method_icalls; Map method_icalls_map; List generated_icall_funcs; diff --git a/modules/mono/glue/builtin_types_glue.h b/modules/mono/glue/builtin_types_glue.h new file mode 100644 index 00000000000..460de84b65a --- /dev/null +++ b/modules/mono/glue/builtin_types_glue.h @@ -0,0 +1,59 @@ +#ifndef BUILTIN_TYPES_GLUE_H +#define BUILTIN_TYPES_GLUE_H + +#include "core/node_path.h" +#include "core/rid.h" + +#include + +#include "../mono_gd/gd_mono_marshal.h" + +MonoBoolean godot_icall_NodePath_is_absolute(NodePath *p_ptr) { + return (MonoBoolean)p_ptr->is_absolute(); +} + +uint32_t godot_icall_NodePath_get_name_count(NodePath *p_ptr) { + return p_ptr->get_name_count(); +} + +MonoString *godot_icall_NodePath_get_name(NodePath *p_ptr, uint32_t p_idx) { + return GDMonoMarshal::mono_string_from_godot(p_ptr->get_name(p_idx)); +} + +uint32_t godot_icall_NodePath_get_subname_count(NodePath *p_ptr) { + return p_ptr->get_subname_count(); +} + +MonoString *godot_icall_NodePath_get_subname(NodePath *p_ptr, uint32_t p_idx) { + return GDMonoMarshal::mono_string_from_godot(p_ptr->get_subname(p_idx)); +} + +MonoString *godot_icall_NodePath_get_concatenated_subnames(NodePath *p_ptr) { + return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_subnames()); +} + +NodePath *godot_icall_NodePath_get_as_property_path(NodePath *p_ptr) { + return memnew(NodePath(p_ptr->get_as_property_path())); +} + +MonoBoolean godot_icall_NodePath_is_empty(NodePath *p_ptr) { + return (MonoBoolean)p_ptr->is_empty(); +} + +uint32_t godot_icall_RID_get_id(RID *p_ptr) { + return p_ptr->get_id(); +} + +void godot_register_builtin_type_icalls() { + mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_as_property_path", (void *)godot_icall_NodePath_get_as_property_path); + mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_concatenated_subnames", (void *)godot_icall_NodePath_get_concatenated_subnames); + mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_name", (void *)godot_icall_NodePath_get_name); + mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_name_count", (void *)godot_icall_NodePath_get_name_count); + mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_subname", (void *)godot_icall_NodePath_get_subname); + mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_subname_count", (void *)godot_icall_NodePath_get_subname_count); + mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_is_absolute", (void *)godot_icall_NodePath_is_absolute); + mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_is_empty", (void *)godot_icall_NodePath_is_empty); + mono_add_internal_call("Godot.NativeCalls::godot_icall_RID_get_id", (void *)godot_icall_RID_get_id); +} + +#endif // BUILTIN_TYPES_GLUE_H diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h index 32988c5afa5..cedc8e9992b 100644 --- a/modules/mono/glue/glue_header.h +++ b/modules/mono/glue/glue_header.h @@ -28,6 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "builtin_types_glue.h" + #include "../csharp_script.h" #include "../mono_gd/gd_mono_class.h" #include "../mono_gd/gd_mono_internals.h" @@ -91,12 +93,6 @@ MonoString *godot_icall_NodePath_operator_String(NodePath *p_np) { return GDMonoMarshal::mono_string_from_godot(p_np->operator String()); } -MonoArray *godot_icall_String_md5_buffer(MonoString *p_str) { - Vector ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_buffer(); - // TODO Check possible Array/Vector problem? - return GDMonoMarshal::Array_to_mono_array(Variant(ret)); -} - // -- RID -- RID *godot_icall_RID_Ctor(Object *p_from) { @@ -115,6 +111,12 @@ void godot_icall_RID_Dtor(RID *p_ptr) { // -- String -- +MonoArray *godot_icall_String_md5_buffer(MonoString *p_str) { + Vector ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_buffer(); + // TODO Check possible Array/Vector problem? + return GDMonoMarshal::Array_to_mono_array(Variant(ret)); +} + MonoString *godot_icall_String_md5_text(MonoString *p_str) { String ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_text(); return GDMonoMarshal::mono_string_from_godot(ret); @@ -303,3 +305,7 @@ MonoObject *godot_icall_Godot_weakref(Object *p_obj) { return GDMonoUtils::create_managed_for_godot_object(CACHED_CLASS(WeakRef), Reference::get_class_static(), Object::cast_to(wref.ptr())); } + +void godot_register_header_icalls() { + godot_register_builtin_type_icalls(); +}