1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-07 12:30:27 +00:00

Add ReadOnlySpan API Overloads

Co-authored-by: Raul Santos <raulsntos@gmail.com>
Co-authored-by: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com>
This commit is contained in:
DE YU
2024-08-30 21:03:40 +08:00
committed by DE-YU_H14
parent 4c4e673344
commit d4695e84a4
3 changed files with 120 additions and 20 deletions

View File

@@ -2348,9 +2348,17 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
int method_bind_count = 0; int method_bind_count = 0;
for (const MethodInterface &imethod : itype.methods) { for (const MethodInterface &imethod : itype.methods) {
Error method_err = _generate_cs_method(itype, imethod, method_bind_count, output); Error method_err = _generate_cs_method(itype, imethod, method_bind_count, output, false);
ERR_FAIL_COND_V_MSG(method_err != OK, method_err, ERR_FAIL_COND_V_MSG(method_err != OK, method_err,
"Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'."); "Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'.");
if (imethod.is_internal) {
// No need to generate span overloads for internal methods.
continue;
}
method_err = _generate_cs_method(itype, imethod, method_bind_count, output, true);
ERR_FAIL_COND_V_MSG(method_err != OK, method_err,
"Failed to generate span overload method '" + imethod.name + "' for class '" + itype.name + "'.");
} }
// Signals // Signals
@@ -2776,7 +2784,7 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
return OK; return OK;
} }
Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output) { Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output, bool p_use_span) {
const TypeInterface *return_type = _get_type_or_singleton_or_null(p_imethod.return_type); const TypeInterface *return_type = _get_type_or_singleton_or_null(p_imethod.return_type);
ERR_FAIL_NULL_V_MSG(return_type, ERR_BUG, "Return type '" + p_imethod.return_type.cname + "' was not found."); ERR_FAIL_NULL_V_MSG(return_type, ERR_BUG, "Return type '" + p_imethod.return_type.cname + "' was not found.");
@@ -2789,6 +2797,35 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
"' from the editor API. Core API cannot have dependencies on the editor API."); "' from the editor API. Core API cannot have dependencies on the editor API.");
} }
if (p_imethod.is_virtual && p_use_span) {
return OK;
}
bool has_span_argument = false;
if (p_use_span) {
if (p_imethod.is_vararg) {
has_span_argument = true;
} else {
for (const ArgumentInterface &iarg : p_imethod.arguments) {
const TypeInterface *arg_type = _get_type_or_singleton_or_null(iarg.type);
ERR_FAIL_NULL_V_MSG(arg_type, ERR_BUG, "Argument type '" + iarg.type.cname + "' was not found.");
if (arg_type->is_span_compatible) {
has_span_argument = true;
break;
}
}
}
if (has_span_argument) {
// Span overloads use the same method bind as the array overloads.
// Since both overloads are generated one after the other, we can decrease the count here
// to ensure the span overload uses the same method bind.
p_method_bind_count--;
}
}
String method_bind_field = CS_STATIC_FIELD_METHOD_BIND_PREFIX + itos(p_method_bind_count); String method_bind_field = CS_STATIC_FIELD_METHOD_BIND_PREFIX + itos(p_method_bind_count);
String arguments_sig; String arguments_sig;
@@ -2835,6 +2872,8 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters); String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters);
bool use_span_for_arg = p_use_span && arg_type->is_span_compatible;
// Add the current arguments to the signature // Add the current arguments to the signature
// If the argument has a default value which is not a constant, we will make it Nullable // If the argument has a default value which is not a constant, we will make it Nullable
{ {
@@ -2846,7 +2885,11 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
arguments_sig += "Nullable<"; arguments_sig += "Nullable<";
} }
if (use_span_for_arg) {
arguments_sig += arg_type->c_type_in;
} else {
arguments_sig += arg_cs_type; arguments_sig += arg_cs_type;
}
if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) { if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) {
arguments_sig += "> "; arguments_sig += "> ";
@@ -2856,7 +2899,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
arguments_sig += iarg.name; arguments_sig += iarg.name;
if (!p_imethod.is_compat && iarg.default_argument.size()) { if (!p_use_span && !p_imethod.is_compat && iarg.default_argument.size()) {
if (iarg.def_param_mode != ArgumentInterface::CONSTANT) { if (iarg.def_param_mode != ArgumentInterface::CONSTANT) {
arguments_sig += " = null"; arguments_sig += " = null";
} else { } else {
@@ -2867,7 +2910,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
icall_params += ", "; icall_params += ", ";
if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT) { if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT && !use_span_for_arg) {
// The default value of an argument must be constant. Otherwise we make it Nullable and do the following: // The default value of an argument must be constant. Otherwise we make it Nullable and do the following:
// Type arg_in = arg.HasValue ? arg.Value : <non-const default value>; // Type arg_in = arg.HasValue ? arg.Value : <non-const default value>;
String arg_or_defval_local = iarg.name; String arg_or_defval_local = iarg.name;
@@ -2927,6 +2970,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
cs_in_expr_is_unsafe |= arg_type->cs_in_expr_is_unsafe; cs_in_expr_is_unsafe |= arg_type->cs_in_expr_is_unsafe;
} }
if (p_use_span && !has_span_argument) {
return OK;
}
// Collect caller name for MethodBind // Collect caller name for MethodBind
if (p_imethod.is_vararg) { if (p_imethod.is_vararg) {
icall_params += ", (godot_string_name)MethodName." + p_imethod.proxy_name + ".NativeValue"; icall_params += ", (godot_string_name)MethodName." + p_imethod.proxy_name + ".NativeValue";
@@ -2934,7 +2981,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Generate method // Generate method
{ {
if (!p_imethod.is_virtual && !p_imethod.requires_object_call) { if (!p_imethod.is_virtual && !p_imethod.requires_object_call && !p_use_span) {
p_output << MEMBER_BEGIN "[DebuggerBrowsable(DebuggerBrowsableState.Never)]\n" p_output << MEMBER_BEGIN "[DebuggerBrowsable(DebuggerBrowsableState.Never)]\n"
<< INDENT1 "private static readonly IntPtr " << method_bind_field << " = "; << INDENT1 "private static readonly IntPtr " << method_bind_field << " = ";
@@ -4734,13 +4781,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype = TypeInterface(); itype = TypeInterface();
itype.name = "VarArg"; itype.name = "VarArg";
itype.cname = itype.name; itype.cname = itype.name;
itype.proxy_name = "Variant[]"; itype.proxy_name = "ReadOnlySpan<Variant>";
itype.cs_type = "params Variant[]"; itype.cs_type = "params Variant[]";
itype.cs_in_expr = "%0 ?? Array.Empty<Variant>()"; itype.cs_in_expr = "%0";
// c_type, c_in and c_arg_in are hard-coded in the generator. // c_type, c_in and c_arg_in are hard-coded in the generator.
// c_out and c_type_out are not applicable to VarArg. // c_out and c_type_out are not applicable to VarArg.
itype.c_arg_in = "&%s_in"; itype.c_arg_in = "&%s_in";
itype.c_type_in = "Variant[]"; itype.c_type_in = "ReadOnlySpan<Variant>";
itype.is_span_compatible = true;
builtin_types.insert(itype.cname, itype); builtin_types.insert(itype.cname, itype);
#define INSERT_ARRAY_FULL(m_name, m_type, m_managed_type, m_proxy_t) \ #define INSERT_ARRAY_FULL(m_name, m_type, m_managed_type, m_proxy_t) \
@@ -4754,9 +4802,10 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_out = "%5return " C_METHOD_MONOARRAY_FROM(m_type) "(%1);\n"; \ itype.c_out = "%5return " C_METHOD_MONOARRAY_FROM(m_type) "(%1);\n"; \
itype.c_arg_in = "&%s_in"; \ itype.c_arg_in = "&%s_in"; \
itype.c_type = #m_managed_type; \ itype.c_type = #m_managed_type; \
itype.c_type_in = itype.proxy_name; \ itype.c_type_in = "ReadOnlySpan<" #m_proxy_t ">"; \
itype.c_type_out = itype.proxy_name; \ itype.c_type_out = itype.proxy_name; \
itype.c_type_is_disposable_struct = true; \ itype.c_type_is_disposable_struct = true; \
itype.is_span_compatible = true; \
builtin_types.insert(itype.name, itype); \ builtin_types.insert(itype.name, itype); \
} }

View File

@@ -265,6 +265,7 @@ class BindingsGenerator {
bool is_singleton = false; bool is_singleton = false;
bool is_singleton_instance = false; bool is_singleton_instance = false;
bool is_ref_counted = false; bool is_ref_counted = false;
bool is_span_compatible = false;
/** /**
* Class is a singleton, but can't be declared as a static class as that would * Class is a singleton, but can't be declared as a static class as that would
@@ -840,7 +841,7 @@ class BindingsGenerator {
Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file); Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file);
Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_iprop, StringBuilder &p_output); Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_iprop, StringBuilder &p_output);
Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output); Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output, bool p_use_span);
Error _generate_cs_signal(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::SignalInterface &p_isignal, StringBuilder &p_output); Error _generate_cs_signal(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::SignalInterface &p_isignal, StringBuilder &p_output);
Error _generate_cs_native_calls(const InternalCall &p_icall, StringBuilder &r_output); Error _generate_cs_native_calls(const InternalCall &p_icall, StringBuilder &r_output);

View File

@@ -394,7 +394,12 @@ namespace Godot.NativeInterop
return array; return array;
} }
public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(Span<byte> p_array) public static godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(Span<byte> p_array)
{
return ConvertSystemArrayToNativePackedByteArray((ReadOnlySpan<byte>)p_array);
}
public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(ReadOnlySpan<byte> p_array)
{ {
if (p_array.IsEmpty) if (p_array.IsEmpty)
return new godot_packed_byte_array(); return new godot_packed_byte_array();
@@ -417,7 +422,12 @@ namespace Godot.NativeInterop
return array; return array;
} }
public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(Span<int> p_array) public static godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(Span<int> p_array)
{
return ConvertSystemArrayToNativePackedInt32Array((ReadOnlySpan<int>)p_array);
}
public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(ReadOnlySpan<int> p_array)
{ {
if (p_array.IsEmpty) if (p_array.IsEmpty)
return new godot_packed_int32_array(); return new godot_packed_int32_array();
@@ -440,7 +450,12 @@ namespace Godot.NativeInterop
return array; return array;
} }
public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(Span<long> p_array) public static godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(Span<long> p_array)
{
return ConvertSystemArrayToNativePackedInt64Array((ReadOnlySpan<long>)p_array);
}
public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(ReadOnlySpan<long> p_array)
{ {
if (p_array.IsEmpty) if (p_array.IsEmpty)
return new godot_packed_int64_array(); return new godot_packed_int64_array();
@@ -463,8 +478,13 @@ namespace Godot.NativeInterop
return array; return array;
} }
public static godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array(Span<float> p_array)
{
return ConvertSystemArrayToNativePackedFloat32Array((ReadOnlySpan<float>)p_array);
}
public static unsafe godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array( public static unsafe godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array(
Span<float> p_array) ReadOnlySpan<float> p_array)
{ {
if (p_array.IsEmpty) if (p_array.IsEmpty)
return new godot_packed_float32_array(); return new godot_packed_float32_array();
@@ -487,8 +507,13 @@ namespace Godot.NativeInterop
return array; return array;
} }
public static godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array(Span<double> p_array)
{
return ConvertSystemArrayToNativePackedFloat64Array((ReadOnlySpan<double>)p_array);
}
public static unsafe godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array( public static unsafe godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array(
Span<double> p_array) ReadOnlySpan<double> p_array)
{ {
if (p_array.IsEmpty) if (p_array.IsEmpty)
return new godot_packed_float64_array(); return new godot_packed_float64_array();
@@ -511,6 +536,11 @@ namespace Godot.NativeInterop
} }
public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(Span<string> p_array) public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(Span<string> p_array)
{
return ConvertSystemArrayToNativePackedStringArray((ReadOnlySpan<string>)p_array);
}
public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(ReadOnlySpan<string> p_array)
{ {
godot_packed_string_array dest = new godot_packed_string_array(); godot_packed_string_array dest = new godot_packed_string_array();
@@ -544,8 +574,13 @@ namespace Godot.NativeInterop
return array; return array;
} }
public static godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array(Span<Vector2> p_array)
{
return ConvertSystemArrayToNativePackedVector2Array((ReadOnlySpan<Vector2>)p_array);
}
public static unsafe godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array( public static unsafe godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array(
Span<Vector2> p_array) ReadOnlySpan<Vector2> p_array)
{ {
if (p_array.IsEmpty) if (p_array.IsEmpty)
return new godot_packed_vector2_array(); return new godot_packed_vector2_array();
@@ -568,8 +603,13 @@ namespace Godot.NativeInterop
return array; return array;
} }
public static godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array(Span<Vector3> p_array)
{
return ConvertSystemArrayToNativePackedVector3Array((ReadOnlySpan<Vector3>)p_array);
}
public static unsafe godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array( public static unsafe godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array(
Span<Vector3> p_array) ReadOnlySpan<Vector3> p_array)
{ {
if (p_array.IsEmpty) if (p_array.IsEmpty)
return new godot_packed_vector3_array(); return new godot_packed_vector3_array();
@@ -592,8 +632,13 @@ namespace Godot.NativeInterop
return array; return array;
} }
public static godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array(Span<Vector4> p_array)
{
return ConvertSystemArrayToNativePackedVector4Array((ReadOnlySpan<Vector4>)p_array);
}
public static unsafe godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array( public static unsafe godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array(
Span<Vector4> p_array) ReadOnlySpan<Vector4> p_array)
{ {
if (p_array.IsEmpty) if (p_array.IsEmpty)
return new godot_packed_vector4_array(); return new godot_packed_vector4_array();
@@ -616,7 +661,12 @@ namespace Godot.NativeInterop
return array; return array;
} }
public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(Span<Color> p_array) public static godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(Span<Color> p_array)
{
return ConvertSystemArrayToNativePackedColorArray((ReadOnlySpan<Color>)p_array);
}
public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(ReadOnlySpan<Color> p_array)
{ {
if (p_array.IsEmpty) if (p_array.IsEmpty)
return new godot_packed_color_array(); return new godot_packed_color_array();