diff options
Diffstat (limited to 'modules/mono/editor/bindings_generator.cpp')
-rw-r--r-- | modules/mono/editor/bindings_generator.cpp | 330 |
1 files changed, 296 insertions, 34 deletions
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 5355cb4e45..c8430234d6 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -76,7 +76,7 @@ #define GLUE_HEADER_FILE "glue_header.h" #define ICALL_PREFIX "godot_icall_" #define SINGLETON_ICALL_SUFFIX "_get_singleton" -#define ICALL_GET_METHODBIND ICALL_PREFIX "Object_ClassDB_get_method" +#define ICALL_GET_METHODBIND "__ClassDB_get_method" #define C_LOCAL_RET "ret" #define C_LOCAL_VARARG_RET "vararg_ret" @@ -95,6 +95,10 @@ #define C_METHOD_MONOSTR_FROM_GODOT C_NS_MONOMARSHAL "::mono_string_from_godot" #define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL "::mono_array_to_" #m_type #define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL "::" #m_type "_to_mono_array" +#define C_METHOD_MANAGED_TO_CALLABLE C_NS_MONOMARSHAL "::managed_to_callable" +#define C_METHOD_MANAGED_FROM_CALLABLE C_NS_MONOMARSHAL "::callable_to_managed" +#define C_METHOD_MANAGED_TO_SIGNAL C_NS_MONOMARSHAL "::signal_info_to_callable" +#define C_METHOD_MANAGED_FROM_SIGNAL C_NS_MONOMARSHAL "::callable_to_signal_info" #define BINDINGS_GENERATOR_VERSION UINT32_C(11) @@ -504,23 +508,23 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf xml_output.append(tag); xml_output.append("</c>"); } else if (tag == "PackedByteArray") { - xml_output.append("<see cref=\"byte\"/>"); + xml_output.append("<see cref=\"T:byte[]\"/>"); } else if (tag == "PackedInt32Array") { - xml_output.append("<see cref=\"int\"/>"); + xml_output.append("<see cref=\"T:int[]\"/>"); + } else if (tag == "PackedInt64Array") { + xml_output.append("<see cref=\"T:long[]\"/>"); } else if (tag == "PackedFloat32Array") { -#ifdef REAL_T_IS_DOUBLE - xml_output.append("<see cref=\"double\"/>"); -#else - xml_output.append("<see cref=\"float\"/>"); -#endif + xml_output.append("<see cref=\"T:float[]\"/>"); + } else if (tag == "PackedFloat64Array") { + xml_output.append("<see cref=\"T:double[]\"/>"); } else if (tag == "PackedStringArray") { - xml_output.append("<see cref=\"string\"/>"); + xml_output.append("<see cref=\"T:string[]\"/>"); } else if (tag == "PackedVector2Array") { - xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Vector2\"/>"); + xml_output.append("<see cref=\"T:" BINDINGS_NAMESPACE ".Vector2[]\"/>"); } else if (tag == "PackedVector3Array") { - xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Vector3\"/>"); + xml_output.append("<see cref=\"T:" BINDINGS_NAMESPACE ".Vector3[]\"/>"); } else if (tag == "PackedColorArray") { - xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Color\"/>"); + xml_output.append("<see cref=\"T:" BINDINGS_NAMESPACE ".Color[]\"/>"); } else { const TypeInterface *target_itype = _get_type_or_null(TypeReference(tag)); @@ -932,7 +936,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { "using System.Runtime.CompilerServices;\n" "\n"); cs_icalls_content.append("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK); - cs_icalls_content.append(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS "\n" INDENT1 OPEN_BLOCK); + cs_icalls_content.append(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS "\n" INDENT1 "{"); cs_icalls_content.append(MEMBER_BEGIN "internal static ulong godot_api_hash = "); cs_icalls_content.append(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + ";\n"); @@ -944,7 +948,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { #define ADD_INTERNAL_CALL(m_icall) \ if (!m_icall.editor_only) { \ cs_icalls_content.append(MEMBER_BEGIN "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \ - cs_icalls_content.append(INDENT2 "internal extern static "); \ + cs_icalls_content.append(INDENT2 "internal static extern "); \ cs_icalls_content.append(m_icall.im_type_out + " "); \ cs_icalls_content.append(m_icall.name + "("); \ cs_icalls_content.append(m_icall.im_sig + ");\n"); \ @@ -1046,7 +1050,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) { #define ADD_INTERNAL_CALL(m_icall) \ if (m_icall.editor_only) { \ cs_icalls_content.append(INDENT2 "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \ - cs_icalls_content.append(INDENT2 "internal extern static "); \ + cs_icalls_content.append(INDENT2 "internal static extern "); \ cs_icalls_content.append(m_icall.im_type_out + " "); \ cs_icalls_content.append(m_icall.name + "("); \ cs_icalls_content.append(m_icall.im_sig + ");\n"); \ @@ -1312,7 +1316,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.append(itype.proxy_name); output.append(").Name);\n" INDENT4 "return singleton;\n" INDENT3 "}\n" INDENT2 "}\n"); - output.append(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \""); + output.append(MEMBER_BEGIN "private static StringName " BINDINGS_NATIVE_NAME_FIELD " = \""); output.append(itype.name); output.append("\";\n"); @@ -1324,7 +1328,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } else if (is_derived_type) { // Add member fields - output.append(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \""); + output.append(MEMBER_BEGIN "private static StringName " BINDINGS_NATIVE_NAME_FIELD " = \""); output.append(itype.name); output.append("\";\n"); @@ -1363,6 +1367,13 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str "Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'."); } + for (const List<SignalInterface>::Element *E = itype.signals_.front(); E; E = E->next()) { + const SignalInterface &isignal = E->get(); + Error method_err = _generate_cs_signal(itype, isignal, output); + ERR_FAIL_COND_V_MSG(method_err != OK, method_err, + "Failed to generate signal '" + isignal.name + "' for class '" + itype.name + "'."); + } + if (itype.is_singleton) { InternalCall singleton_icall = InternalCall(itype.api_type, ICALL_PREFIX + itype.name + SINGLETON_ICALL_SUFFIX, "IntPtr"); @@ -1424,7 +1435,16 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte } if (getter && setter) { - ERR_FAIL_COND_V(getter->return_type.cname != setter->arguments.back()->get().type.cname, ERR_BUG); + const ArgumentInterface &setter_first_arg = setter->arguments.back()->get(); + if (getter->return_type.cname != setter_first_arg.type.cname) { + // Special case for Node::set_name + bool whitelisted = getter->return_type.cname == name_cache.type_StringName && + setter_first_arg.type.cname == name_cache.type_String; + + ERR_FAIL_COND_V_MSG(!whitelisted, ERR_BUG, + "Return type from getter doesn't match first argument of setter for property: '" + + p_itype.name + "." + String(p_iprop.cname) + "'."); + } } const TypeReference &proptype_name = getter ? getter->return_type : setter->arguments.back()->get().type; @@ -1525,7 +1545,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf const TypeInterface *return_type = _get_type_or_placeholder(p_imethod.return_type); - String method_bind_field = "method_bind_" + itos(p_method_bind_count); + String method_bind_field = "__method_bind_" + itos(p_method_bind_count); String arguments_sig; String cs_in_statements; @@ -1612,7 +1632,8 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf { if (!p_imethod.is_virtual && !p_imethod.requires_object_call) { p_output.append(MEMBER_BEGIN "[DebuggerBrowsable(DebuggerBrowsableState.Never)]" MEMBER_BEGIN "private static IntPtr "); - p_output.append(method_bind_field + " = Object." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \""); + p_output.append(method_bind_field); + p_output.append(" = Object." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \""); p_output.append(p_imethod.name); p_output.append("\");\n"); } @@ -1726,6 +1747,106 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf return OK; } +Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::SignalInterface &p_isignal, StringBuilder &p_output) { + String arguments_sig; + + // Retrieve information from the arguments + for (const List<ArgumentInterface>::Element *F = p_isignal.arguments.front(); F; F = F->next()) { + const ArgumentInterface &iarg = F->get(); + const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type); + + // Add the current arguments to the signature + + if (F != p_isignal.arguments.front()) + arguments_sig += ", "; + + arguments_sig += arg_type->cs_type; + arguments_sig += " "; + arguments_sig += iarg.name; + } + + // Generate signal + { + if (p_isignal.method_doc && p_isignal.method_doc->description.size()) { + String xml_summary = bbcode_to_xml(fix_doc_description(p_isignal.method_doc->description), &p_itype); + Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>(); + + if (summary_lines.size()) { + p_output.append(MEMBER_BEGIN "/// <summary>\n"); + + for (int i = 0; i < summary_lines.size(); i++) { + p_output.append(INDENT2 "/// "); + p_output.append(summary_lines[i]); + p_output.append("\n"); + } + + p_output.append(INDENT2 "/// </summary>"); + } + } + + if (p_isignal.is_deprecated) { + if (p_isignal.deprecation_message.empty()) + WARN_PRINT("An empty deprecation message is discouraged. Signal: '" + p_isignal.proxy_name + "'."); + + p_output.append(MEMBER_BEGIN "[Obsolete(\""); + p_output.append(p_isignal.deprecation_message); + p_output.append("\")]"); + } + + String delegate_name = p_isignal.proxy_name; + delegate_name += "Handler"; // Delegate name is [SignalName]Handler + + // Generate delegate + p_output.append(MEMBER_BEGIN "public delegate void "); + p_output.append(delegate_name); + p_output.append("("); + p_output.append(arguments_sig); + p_output.append(");\n"); + + // TODO: + // Could we assume the StringName instance of signal name will never be freed (it's stored in ClassDB) before the managed world is unloaded? + // If so, we could store the pointer we get from `data_unique_pointer()` instead of allocating StringName here. + + // Cached signal name (StringName) + p_output.append(MEMBER_BEGIN "[DebuggerBrowsable(DebuggerBrowsableState.Never)]" MEMBER_BEGIN "private static StringName __signal_name_"); + p_output.append(p_isignal.name); + p_output.append(" = \""); + p_output.append(p_isignal.name); + p_output.append("\";\n"); + + // Generate event + p_output.append(MEMBER_BEGIN "[Signal]" MEMBER_BEGIN "public "); + + if (p_itype.is_singleton) + p_output.append("static "); + + p_output.append("event "); + p_output.append(delegate_name); + p_output.append(" "); + p_output.append(p_isignal.proxy_name); + p_output.append("\n" OPEN_BLOCK_L2); + + if (p_itype.is_singleton) + p_output.append("add => Singleton.Connect(__signal_name_"); + else + p_output.append("add => Connect(__signal_name_"); + + p_output.append(p_isignal.name); + p_output.append(", new Callable(value));\n"); + + if (p_itype.is_singleton) + p_output.append(INDENT3 "remove => Singleton.Disconnect(__signal_name_"); + else + p_output.append(INDENT3 "remove => Disconnect(__signal_name_"); + + p_output.append(p_isignal.name); + p_output.append(", new Callable(value));\n"); + p_output.append(CLOSE_BLOCK_L2); + } + + return OK; +} + Error BindingsGenerator::generate_glue(const String &p_output_dir) { ERR_FAIL_COND_V(!initialized, ERR_UNCONFIGURED); @@ -2479,13 +2600,92 @@ bool BindingsGenerator::_populate_object_type_interfaces() { } } + // Populate signals + + const HashMap<StringName, MethodInfo> &signal_map = class_info->signal_map; + const StringName *k = NULL; + + while ((k = signal_map.next(k))) { + SignalInterface isignal; + + const MethodInfo &method_info = signal_map.get(*k); + + isignal.name = method_info.name; + isignal.cname = method_info.name; + + int argc = method_info.arguments.size(); + + for (int i = 0; i < argc; i++) { + PropertyInfo arginfo = method_info.arguments[i]; + + String orig_arg_name = arginfo.name; + + ArgumentInterface iarg; + iarg.name = orig_arg_name; + + if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + iarg.type.cname = arginfo.class_name; + iarg.type.is_enum = true; + } else if (arginfo.class_name != StringName()) { + iarg.type.cname = arginfo.class_name; + } else if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { + iarg.type.cname = arginfo.hint_string; + } else if (arginfo.type == Variant::NIL) { + iarg.type.cname = name_cache.type_Variant; + } else { + if (arginfo.type == Variant::INT) { + iarg.type.cname = _get_int_type_name_from_meta(GodotTypeInfo::METADATA_NONE); + } else if (arginfo.type == Variant::FLOAT) { + iarg.type.cname = _get_float_type_name_from_meta(GodotTypeInfo::METADATA_NONE); + } else { + iarg.type.cname = Variant::get_type_name(arginfo.type); + } + } + + iarg.name = escape_csharp_keyword(snake_to_camel_case(iarg.name)); + + isignal.add_argument(iarg); + } + + isignal.proxy_name = escape_csharp_keyword(snake_to_pascal_case(isignal.name)); + + // Prevent the signal and its enclosing type from sharing the same name + if (isignal.proxy_name == itype.proxy_name) { + _log("Name of signal '%s' is ambiguous with the name of its enclosing class '%s'. Renaming signal to '%s_'\n", + isignal.proxy_name.utf8().get_data(), itype.proxy_name.utf8().get_data(), isignal.proxy_name.utf8().get_data()); + + isignal.proxy_name += "_"; + } + + if (itype.find_property_by_proxy_name(isignal.proxy_name) || itype.find_method_by_proxy_name(isignal.proxy_name)) { + // ClassDB allows signal names that conflict with method or property names. + // While registering a signal with a conflicting name is considered wrong, + // it may still happen and it may take some time until someone fixes the name. + // We can't allow the bindings to be in a broken state while we wait for a fix; + // that's why we must handle this possibility by renaming the signal. + isignal.proxy_name += "Signal"; + } + + if (itype.class_doc) { + for (int i = 0; i < itype.class_doc->signals.size(); i++) { + const DocData::MethodDoc &signal_doc = itype.class_doc->signals[i]; + if (signal_doc.name == isignal.name) { + isignal.method_doc = &signal_doc; + break; + } + } + } + + itype.signals_.push_back(isignal); + } + // Populate enums and constants List<String> constants; ClassDB::get_integer_constant_list(type_cname, &constants, true); const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map; - const StringName *k = NULL; + k = NULL; while ((k = enum_map.next(k))) { StringName enum_proxy_cname = *k; @@ -2587,8 +2787,15 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar #endif break; case Variant::STRING: + case Variant::STRING_NAME: case Variant::NODE_PATH: - r_iarg.default_argument = "\"" + r_iarg.default_argument + "\""; + if (r_iarg.type.cname == name_cache.type_StringName || r_iarg.type.cname == name_cache.type_NodePath) { + r_iarg.default_argument = "(%s)\"" + r_iarg.default_argument + "\""; + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; + } else { + CRASH_COND(r_iarg.type.cname != name_cache.type_String); + r_iarg.default_argument = "\"" + r_iarg.default_argument + "\""; + } break; case Variant::TRANSFORM: if (p_val.operator Transform() == Transform()) @@ -2630,8 +2837,8 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar case Variant::ARRAY: case Variant::PACKED_BYTE_ARRAY: case Variant::PACKED_INT32_ARRAY: - case Variant::PACKED_FLOAT32_ARRAY: case Variant::PACKED_INT64_ARRAY: + case Variant::PACKED_FLOAT32_ARRAY: case Variant::PACKED_FLOAT64_ARRAY: case Variant::PACKED_STRING_ARRAY: case Variant::PACKED_VECTOR2_ARRAY: @@ -2646,8 +2853,13 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar r_iarg.default_argument = Variant::get_type_name(p_val.get_type()) + ".Identity"; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; break; - default: { - } + case Variant::CALLABLE: + case Variant::SIGNAL: + CRASH_NOW_MSG("Parameter of type '" + String(r_iarg.type.cname) + "' cannot have a default value."); + break; + default: + CRASH_NOW_MSG("Unexpected Variant type: " + itos(p_val.get_type())); + break; } if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type.cname == name_cache.type_Variant && r_iarg.default_argument != "null") @@ -2672,7 +2884,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.c_type_out = "GDMonoMarshal::M_" #m_type; \ itype.cs_in = "ref %s"; \ /* in cs_out, im_type_out (%3) includes the 'out ' part */ \ - itype.cs_out = "%0(%1, %3 argRet); return (%2)argRet;"; \ + itype.cs_out = "%0(%1, %3 argRet); return argRet;"; \ itype.im_type_out = "out " + itype.cs_type; \ itype.ret_as_byref_arg = true; \ builtin_types.insert(itype.cname, itype); \ @@ -2749,7 +2961,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.im_type_out = "out " + itype.name; itype.cs_in = "ref %0"; /* in cs_out, im_type_out (%3) includes the 'out ' part */ - itype.cs_out = "%0(%1, %3 argRet); return (%2)argRet;"; + itype.cs_out = "%0(%1, %3 argRet); return argRet;"; itype.ret_as_byref_arg = true; builtin_types.insert(itype.cname, itype); @@ -2766,7 +2978,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.im_type_out = "out " + itype.name; itype.cs_in = "ref %0"; /* in cs_out, im_type_out (%3) includes the 'out ' part */ - itype.cs_out = "%0(%1, %3 argRet); return (%2)argRet;"; + itype.cs_out = "%0(%1, %3 argRet); return argRet;"; itype.ret_as_byref_arg = true; builtin_types.insert(itype.cname, itype); } @@ -2792,7 +3004,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.im_type_out = "out " + itype.proxy_name; itype.cs_in = "ref %0"; /* in cs_out, im_type_out (%3) includes the 'out ' part */ - itype.cs_out = "%0(%1, %3 argRet); return (%2)argRet;"; + itype.cs_out = "%0(%1, %3 argRet); return argRet;"; itype.ret_as_byref_arg = true; builtin_types.insert(itype.cname, itype); @@ -2814,7 +3026,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.im_type_out = "out " + itype.proxy_name; itype.cs_in = "ref %0"; /* in cs_out, im_type_out (%3) includes the 'out ' part */ - itype.cs_out = "%0(%1, %3 argRet); return (%2)argRet;"; + itype.cs_out = "%0(%1, %3 argRet); return argRet;"; itype.ret_as_byref_arg = true; builtin_types.insert(itype.cname, itype); } @@ -2835,6 +3047,24 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.im_type_out = itype.proxy_name; builtin_types.insert(itype.cname, itype); + // StringName + itype = TypeInterface(); + itype.name = "StringName"; + itype.cname = itype.name; + itype.proxy_name = "StringName"; + itype.c_in = "\t%0 %1_in = %1 ? *%1 : StringName();\n"; + itype.c_out = "\treturn memnew(StringName(%1));\n"; + itype.c_arg_in = "&%s_in"; + itype.c_type = itype.name; + itype.c_type_in = itype.c_type + "*"; + itype.c_type_out = itype.c_type + "*"; + itype.cs_type = itype.proxy_name; + itype.cs_in = "StringName." CS_SMETHOD_GETINSTANCE "(%0)"; + itype.cs_out = "return new %2(%0(%1));"; + itype.im_type_in = "IntPtr"; + itype.im_type_out = "IntPtr"; + builtin_types.insert(itype.cname, itype); + // NodePath itype = TypeInterface(); itype.name = "NodePath"; @@ -2883,6 +3113,40 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.im_type_out = itype.proxy_name; builtin_types.insert(itype.cname, itype); + // Callable + itype = TypeInterface::create_value_type(String("Callable")); + itype.c_in = "\t%0 %1_in = " C_METHOD_MANAGED_TO_CALLABLE "(*%1);\n"; + itype.c_out = "\t*%3 = " C_METHOD_MANAGED_FROM_CALLABLE "(%1);\n"; + itype.c_arg_in = "&%s_in"; + itype.c_type_in = "GDMonoMarshal::M_Callable*"; + itype.c_type_out = "GDMonoMarshal::M_Callable"; + itype.cs_in = "ref %s"; + /* in cs_out, im_type_out (%3) includes the 'out ' part */ + itype.cs_out = "%0(%1, %3 argRet); return argRet;"; + itype.im_type_out = "out " + itype.cs_type; + itype.ret_as_byref_arg = true; + builtin_types.insert(itype.cname, itype); + + // Signal + itype = TypeInterface(); + itype.name = "Signal"; + itype.cname = itype.name; + itype.proxy_name = "SignalInfo"; + itype.c_in = "\t%0 %1_in = " C_METHOD_MANAGED_TO_SIGNAL "(*%1);\n"; + itype.c_out = "\t*%3 = " C_METHOD_MANAGED_FROM_SIGNAL "(%1);\n"; + itype.c_arg_in = "&%s_in"; + itype.c_type = itype.name; + itype.c_type_in = "GDMonoMarshal::M_SignalInfo*"; + itype.c_type_out = "GDMonoMarshal::M_SignalInfo"; + itype.cs_in = "ref %s"; + /* in cs_out, im_type_out (%3) includes the 'out ' part */ + itype.cs_out = "%0(%1, %3 argRet); return argRet;"; + itype.cs_type = itype.proxy_name; + itype.im_type_in = "ref " + itype.cs_type; + itype.im_type_out = "out " + itype.cs_type; + itype.ret_as_byref_arg = true; + builtin_types.insert(itype.cname, itype); + // VarArg (fictitious type to represent variable arguments) itype = TypeInterface(); itype.name = "VarArg"; @@ -2917,13 +3181,11 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { #define INSERT_ARRAY(m_type, m_proxy_t) INSERT_ARRAY_FULL(m_type, m_type, m_proxy_t) INSERT_ARRAY(PackedInt32Array, int); + INSERT_ARRAY(PackedInt64Array, long); INSERT_ARRAY_FULL(PackedByteArray, PackedByteArray, byte); -#ifdef REAL_T_IS_DOUBLE - INSERT_ARRAY(PackedFloat32Array, double); -#else INSERT_ARRAY(PackedFloat32Array, float); -#endif + INSERT_ARRAY(PackedFloat64Array, double); INSERT_ARRAY(PackedStringArray, string); |