eolian_mono: make struct immutable

Summary:
Immutable value type is recommeneded for struct type in cs world.
`DO NOT define mutable value types.`
(see, https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/struct)

Also, this patch include refactoring of generated struct types.
1. Change field type to property type that have only getter. it will fix CA1051(ref T8397).
2. Remove internal NativeStruct. there is private field for marshalling struct instead.
3. Fix some test cases that change value inside struct. because struct is immutable.

Test Plan: meson build -Dbindings=mono,cxx -Dmono-beta=true

Reviewers: woohyun, felipealmeida, Jaehyun_Cho

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Maniphest Tasks: T8397

Differential Revision: https://phab.enlightenment.org/D11146
This commit is contained in:
Yeongjong Lee 2020-01-28 14:46:10 +09:00 committed by WooHyun Jung
parent b3c0da13d8
commit 581bec9598
10 changed files with 316 additions and 276 deletions

View File

@ -129,7 +129,7 @@ struct marshall_type_visitor_generate
, {"event", nullptr, [&] , {"event", nullptr, [&]
{ {
regular_type_def r = regular; regular_type_def r = regular;
r.base_type = "Efl.Event.NativeStruct"; r.base_type = "Efl.Event";
r.namespaces.clear(); r.namespaces.clear();
return r; return r;
}} }}
@ -190,7 +190,7 @@ struct marshall_type_visitor_generate
{ {
if ((is_out || is_return) && is_ptr) if ((is_out || is_return) && is_ptr)
return as_generator("System.IntPtr").generate(sink, attributes::unused, *context); return as_generator("System.IntPtr").generate(sink, attributes::unused, *context);
return as_generator(string << ".NativeStruct") return as_generator(string)
.generate(sink, name_helpers::type_full_managed_name(regular), *context); .generate(sink, name_helpers::type_full_managed_name(regular), *context);
} }
else if (eina::optional<bool> b = type_match::get_match else if (eina::optional<bool> b = type_match::get_match

View File

@ -331,7 +331,8 @@ inline std::string enum_field_managed_name(std::string name)
inline std::string to_field_name(std::string const& in) inline std::string to_field_name(std::string const& in)
{ {
return utils::capitalize(in); std::vector<std::string> names = utils::split(in, '_');
return utils::to_camel_case(names);
} }
@ -583,6 +584,16 @@ struct struct_field_name_generator
} }
} const struct_field_name {}; } const struct_field_name {};
// Property names //
struct struct_property_name_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const
{
return as_generator(string).generate(sink, name_helpers::managed_name(field.name), context);
}
} const struct_property_name {};
} // namespace name_helpers } // namespace name_helpers
} // namespace eolian_mono } // namespace eolian_mono
@ -615,12 +626,19 @@ struct is_eager_generator<eolian_mono::name_helpers::struct_field_name_generator
template <> template <>
struct is_generator< ::eolian_mono::name_helpers::struct_field_name_generator> : std::true_type {}; struct is_generator< ::eolian_mono::name_helpers::struct_field_name_generator> : std::true_type {};
template <>
struct is_eager_generator<eolian_mono::name_helpers::struct_property_name_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::name_helpers::struct_property_name_generator> : std::true_type {};
namespace type_traits { namespace type_traits {
template <> template <>
struct attributes_needed<struct ::eolian_mono::name_helpers::klass_full_concrete_or_interface_name_generator> : std::integral_constant<int, 1> {}; struct attributes_needed<struct ::eolian_mono::name_helpers::klass_full_concrete_or_interface_name_generator> : std::integral_constant<int, 1> {};
template <> template <>
struct attributes_needed< ::eolian_mono::name_helpers::struct_field_name_generator> : std::integral_constant<int, 1> {}; struct attributes_needed< ::eolian_mono::name_helpers::struct_field_name_generator> : std::integral_constant<int, 1> {};
template <>
struct attributes_needed< ::eolian_mono::name_helpers::struct_property_name_generator> : std::integral_constant<int, 1> {};
} }

View File

@ -181,7 +181,6 @@ struct to_external_field_convert_generator
template <typename OutputIterator, typename Context> template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const
{ {
auto const& indent = current_indentation(context);
auto field_name = name_helpers::to_field_name(field.name); auto field_name = name_helpers::to_field_name(field.name);
auto regular = efl::eina::get<attributes::regular_type_def>(&field.type.original_type); auto regular = efl::eina::get<attributes::regular_type_def>(&field.type.original_type);
auto klass = efl::eina::get<attributes::klass_name>(&field.type.original_type); auto klass = efl::eina::get<attributes::klass_name>(&field.type.original_type);
@ -191,113 +190,108 @@ struct to_external_field_convert_generator
{ {
auto interface_name = name_helpers::klass_full_interface_name(*klass); auto interface_name = name_helpers::klass_full_interface_name(*klass);
if (!as_generator( if (!as_generator(
"\n" "(" << interface_name << ") Efl.Eo.Globals.CreateWrapperFor(" << string << ");"
<< indent << scope_tab << scope_tab << "_external_struct." << string
<< " = (" << interface_name << ") Efl.Eo.Globals.CreateWrapperFor(_internal_struct." << string << ");\n"
).generate(sink, std::make_tuple(field_name, field_name), context)) ).generate(sink, std::make_tuple(field_name, field_name), context))
return false; return false;
} }
else if (field.type.c_type == "Eina_Binbuf *" || field.type.c_type == "const Eina_Binbuf *") else if (field.type.c_type == "Eina_Binbuf *" || field.type.c_type == "const Eina_Binbuf *")
{ {
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "_external_struct." << string << " = new " << type << "(_internal_struct." << string << ", false);\n") "new " << type << "(" << string << ", false);")
.generate(sink, std::make_tuple(field_name, field.type, field_name), context)) .generate(sink, std::make_tuple(field.type, field_name), context))
return false; return false;
} }
else if (complex && (complex->outer.base_type == "array")) else if (complex && (complex->outer.base_type == "array"))
{ {
// Always assumes pointer // Always assumes pointer
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.Globals.NativeArrayTo" << type << "(_internal_struct." << string << ");\n") "Efl.Eo.Globals.NativeArrayTo" << type << "(" << string << ");")
.generate(sink, std::make_tuple(field_name, field.type, field_name), context)) .generate(sink, std::make_tuple(field.type, field_name), context))
return false; return false;
} }
else if (complex && (complex->outer.base_type == "list")) else if (complex && (complex->outer.base_type == "list"))
{ {
// Always assumes pointer // Always assumes pointer
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.Globals.NativeListTo" << type << "(_internal_struct." << string << ");\n") "Efl.Eo.Globals.NativeListTo" << type << "(" << string << ");")
.generate(sink, std::make_tuple(field_name, field.type, field_name), context)) .generate(sink, std::make_tuple(field.type, field_name), context))
return false; return false;
} }
else if (complex && complex->outer.base_type == "hash") else if (complex && complex->outer.base_type == "hash")
{ {
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "_external_struct." << string << " = new " << type << "(_internal_struct." << string << ", false, false, false);\n") "new " << type << "(" << string << ", false, false, false);")
.generate(sink, std::make_tuple(field_name, field.type, field_name), context)) .generate(sink, std::make_tuple(field.type, field_name), context))
return false; return false;
} }
else if (complex && complex->outer.base_type == "iterator") else if (complex && complex->outer.base_type == "iterator")
{ {
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.Globals.IteratorTo" << type << "(_internal_struct." << string << ");\n") "Efl.Eo.Globals.IteratorTo" << type << "(" << string << ");")
.generate(sink, std::make_tuple(field_name, field.type, field_name), context)) .generate(sink, std::make_tuple(field.type, field_name), context))
return false; return false;
} }
else if (field.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular)) else if (field.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular))
{ {
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "_external_struct." << string << " = Eina.PrimitiveConversion.PointerToManaged<" << type << ">(_internal_struct." << string << ");\n") "Eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << string << ");")
.generate(sink, std::make_tuple(field_name, field.type, field_name), context)) .generate(sink, std::make_tuple(field.type, field_name), context))
return false; return false;
} }
else if (helpers::need_struct_conversion(regular)) else if (helpers::need_struct_conversion(regular))
{ {
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << ";\n") string << ";")
.generate(sink, std::make_tuple(field_name, field_name), context)) .generate(sink, field_name, context))
return false; return false;
} }
else if (regular && (regular->base_type == "string" || regular->base_type == "mstring" || regular->base_type == "stringshare")) else if (regular && (regular->base_type == "string" || regular->base_type == "mstring" || regular->base_type == "stringshare"))
{ {
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "_external_struct." << string << " = Eina.StringConversion.NativeUtf8ToManagedString(_internal_struct." << string << ");\n") "Eina.StringConversion.NativeUtf8ToManagedString(" << string << ");")
.generate(sink, std::make_tuple(field_name, field_name), context)) .generate(sink, std::make_tuple(field_name, field_name), context))
return false; return false;
} }
else if (field.type.c_type == "Eina_Slice" || field.type.c_type == "const Eina_Slice" else if (field.type.c_type == "Eina_Slice" || field.type.c_type == "const Eina_Slice"
|| field.type.c_type == "Eina_Rw_Slice" || field.type.c_type == "const Eina_Rw_Slice") || field.type.c_type == "Eina_Rw_Slice" || field.type.c_type == "const Eina_Rw_Slice")
{ {
if (!as_generator( if (!as_generator(field_name << ";")
"\n" <<
indent << scope_tab << scope_tab << "_external_struct." << field_name << ".Len = _internal_struct." << field_name << ".Len;\n" <<
indent << scope_tab << scope_tab << "_external_struct." << field_name << ".Mem = _internal_struct." << field_name << ".Mem;\n")
.generate(sink, attributes::unused, context)) .generate(sink, attributes::unused, context))
return false; return false;
} }
else if (field.type.c_type == "Eina_Value" || field.type.c_type == "const Eina_Value") else if (field.type.c_type == "Eina_Value" || field.type.c_type == "const Eina_Value")
{ {
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "_external_struct." << string << " = new Eina.Value(_internal_struct." << string << ");\n" "new Eina.Value(" << string << ");"
).generate(sink, std::make_tuple(field_name, field_name), context)) ).generate(sink, std::make_tuple(field_name), context))
return false; return false;
} }
else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *") else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *")
{ {
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "_external_struct." << string << " = new Eina.Value(_internal_struct." << string << ", Eina.Ownership.Unmanaged);\n" "new Eina.Value(" << string << ", Eina.Ownership.Unmanaged);"
).generate(sink, std::make_tuple(field_name, field_name), context)) ).generate(sink, std::make_tuple(field_name), context))
return false; return false;
} }
else if (!field.type.is_ptr && regular && regular->base_type == "bool") else if (!field.type.is_ptr && regular && regular->base_type == "bool")
{ {
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << " != 0;\n" string << " != 0;"
).generate(sink, std::make_tuple(field_name, field_name), context)) ).generate(sink, std::make_tuple(field_name), context))
return false; return false;
} }
else if (!field.type.is_ptr && regular && regular->base_type == "char") else if (!field.type.is_ptr && regular && regular->base_type == "char")
{ {
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "_external_struct." << string << " = (char)_internal_struct." << string << ";\n" "(char)" << string << ";"
).generate(sink, std::make_tuple(field_name, field_name), context)) ).generate(sink, std::make_tuple(field_name), context))
return false; return false;
} }
else // primitives and enums else // primitives and enums
{ {
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << ";\n") field_name << ";"
.generate(sink, std::make_tuple(field_name, field_name), context)) ).generate(sink, attributes::unused, context))
return false; return false;
} }
return true; return true;
@ -306,22 +300,12 @@ struct to_external_field_convert_generator
// Internal Struct // // Internal Struct //
struct struct_internal_definition_generator struct struct_private_property_generator
{ {
template <typename OutputIterator, typename Context> template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const
{ {
auto const& indent = current_indentation(context); auto const& indent = current_indentation(context);
if (!as_generator
(
"#pragma warning disable CS1591\n\n"
<< indent << "/// <summary>Internal wrapper for struct " << string << ".</summary>\n"
<< indent << "[StructLayout(LayoutKind.Sequential)]\n"
<< indent << "internal struct " << string << "\n"
<< indent << "{\n"
)
.generate(sink, std::make_tuple<>(binding_struct_name(struct_), struct_internal_decl_name()), context))
return false;
// iterate struct fields // iterate struct fields
for (auto const& field : struct_.fields) for (auto const& field : struct_.fields)
@ -337,7 +321,7 @@ struct struct_internal_definition_generator
|| regular->base_type == "any_value_ref"))) || regular->base_type == "any_value_ref")))
{ {
if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n" if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n"
<< indent << scope_tab << "public System.IntPtr " << field_name << ";\n") << indent << scope_tab << "private System.IntPtr " << field_name << ";\n")
.generate(sink, nullptr, context)) .generate(sink, nullptr, context))
return false; return false;
} }
@ -345,7 +329,7 @@ struct struct_internal_definition_generator
&& regular->base_type == "bool") && regular->base_type == "bool")
{ {
if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n" if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n"
<< indent << scope_tab << "public System.Byte " << field_name << ";\n") << indent << scope_tab << "private System.Byte " << field_name << ";\n")
.generate(sink, nullptr, context)) .generate(sink, nullptr, context))
return false; return false;
} }
@ -353,12 +337,12 @@ struct struct_internal_definition_generator
&& regular->base_type == "char") && regular->base_type == "char")
{ {
if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n" if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n"
<< indent << scope_tab << "public System.Byte " << field_name << ";\n") << indent << scope_tab << "private System.Byte " << field_name << ";\n")
.generate(sink, nullptr, context)) .generate(sink, nullptr, context))
return false; return false;
} }
else if (!as_generator(indent << scope_tab << eolian_mono::marshall_annotation(false) << "\n" else if (!as_generator(indent << scope_tab << eolian_mono::marshall_annotation(false) << "\n"
<< indent << scope_tab << "public " << eolian_mono::marshall_type(false) << " " << string << ";\n") << indent << scope_tab << "private " << eolian_mono::marshall_type(false) << " " << string << ";\n")
.generate(sink, std::make_tuple(field.type, field.type, field_name), context)) .generate(sink, std::make_tuple(field.type, field.type, field_name), context))
return false; return false;
} }
@ -369,59 +353,18 @@ struct struct_internal_definition_generator
// those 'mini-amd64.c condition fields not met' crashes. // those 'mini-amd64.c condition fields not met' crashes.
if (struct_.fields.size() == 0) if (struct_.fields.size() == 0)
{ {
if (!as_generator(indent << scope_tab << "internal IntPtr field;\n").generate(sink, nullptr, context)) if (!as_generator(indent << scope_tab << "/// <summary>Placeholder field</summary>\n"
<< indent << scope_tab << "private IntPtr field;\n").generate(sink, nullptr, context))
return false; return false;
} }
auto external_name = binding_struct_name(struct_); if(!as_generator("\n")
auto internal_name = binding_struct_internal_name(struct_); .generate(sink, attributes::unused, context))
// to internal
if (!as_generator(
indent << scope_tab << "/// <summary>Implicit conversion to the internal/marshalling representation.</summary>\n"
<< indent << scope_tab << "public static implicit operator " << string << "(" << string << " _external_struct)\n"
<< indent << scope_tab << "{\n"
<< indent << scope_tab << scope_tab << "var _internal_struct = new " << string << "();\n"
).generate(sink, std::make_tuple(internal_name, external_name, internal_name), context))
return false; return false;
for (auto const& field : struct_.fields)
{
if (!to_internal_field_convert.generate(sink, field, context))
return false;
}
if (!as_generator(indent << scope_tab << scope_tab << "return _internal_struct;\n"
<< indent << scope_tab << "}\n\n").generate(sink, nullptr, context))
return false;
// to managed
if (!as_generator(
indent << scope_tab << "/// <summary>Implicit conversion to the managed representation.</summary>\n"
<< indent << scope_tab << "public static implicit operator " << string << "(" << string << " _internal_struct)\n"
<< indent << scope_tab << "{\n"
<< indent << scope_tab << scope_tab << "var _external_struct = new " << string << "();\n"
).generate(sink, std::make_tuple(external_name, internal_name, external_name), context))
return false;
for (auto const& field : struct_.fields)
{
if (!to_external_field_convert.generate(sink, field, context))
return false;
}
if (!as_generator(indent << scope_tab << scope_tab << "return _external_struct;\n"
<< indent << scope_tab << "}\n").generate(sink, nullptr, context))
return false;
// close internal class
if(!as_generator(indent << "}\n"
<< "#pragma warning restore CS1591\n"
).generate(sink, attributes::unused, context)) return false;
return true; return true;
} }
} const struct_internal_definition {}; } const struct_private_property {};
// Managed Struct // // Managed Struct //
@ -454,34 +397,22 @@ struct struct_definition_generator
return false; return false;
if (!as_generator( if (!as_generator(
indent << scope_tab << "public static implicit operator " << struct_name << "(\n" indent << scope_tab << "public static implicit operator " << struct_name << "(("
<< indent << scope_tab << scope_tab << "(\n" << (field_argument_decl % ", ")
<< ((indent << scope_tab << scope_tab << " " << field_argument_decl) % ",\n") << "\n" << ") tuple)\n"
<< indent << scope_tab << scope_tab << ") tuple)\n"
<< indent << scope_tab << "{\n"
).generate(sink, struct_.fields, context)) ).generate(sink, struct_.fields, context))
return false; return false;
// object constructor // object constructor
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "return new " << struct_name << "{\n" indent << scope_tab << scope_tab << "=> new " << struct_name << "("
).generate(sink, attributes::unused, context)) ).generate(sink, attributes::unused, context))
return false; return false;
for (const auto& field: struct_.fields)
{
auto field_name = name_helpers::to_field_name(field.name);
if (!as_generator(
indent << scope_tab << scope_tab << scope_tab << field_name << " = tuple." << field_name << ",\n"
).generate(sink, attributes::unused, context))
return false;
}
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "};\n" (("tuple." << struct_field_name) % ", ")
<< indent << scope_tab << "}\n" << ");\n\n"
).generate(sink, attributes::unused, context)) ).generate(sink, struct_.fields, context))
return false; return false;
return true; return true;
@ -528,10 +459,11 @@ struct struct_definition_generator
// assigments // assigments
for (auto const& field : struct_.fields) for (auto const& field : struct_.fields)
{ {
auto field_name = name_helpers::to_field_name(field.name); auto field_name = name_helpers::managed_name(field.name);
auto param_name = name_helpers::to_field_name(field.name);
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << field_name << " = this." << field_name << ";\n" indent << scope_tab << scope_tab << param_name << " = this." << field_name << ";\n"
).generate(sink, attributes::unused, context)) ).generate(sink, attributes::unused, context))
return false; return false;
} }
@ -561,6 +493,9 @@ struct struct_definition_generator
.generate(sink, attributes::unused, context)) .generate(sink, attributes::unused, context))
return false; return false;
if (!struct_private_property.generate(sink, struct_, change_indentation(indent, context)))
return false;
// iterate struct fields // iterate struct fields
for (auto const& field : struct_.fields) for (auto const& field : struct_.fields)
{ {
@ -574,23 +509,13 @@ struct struct_definition_generator
return false; return false;
} }
if (!as_generator(indent << scope_tab << "public " << type << " " << name_helpers::to_field_name(field.name) << ";\n").generate(sink, field.type, context)) if (!as_generator(indent << scope_tab << "public " << type << " " << name_helpers::managed_name(field.name) << " { get => " << to_external_field_convert << " }\n").generate(sink, std::make_tuple(field.type, field), context))
return false; return false;
} }
auto struct_name = binding_struct_name(struct_); auto struct_name = binding_struct_name(struct_);
// Check whether this is an extern struct without declared fields in .eo file and generate a if (struct_.fields.size() != 0)
// placeholder field if positive.
// Mono's JIT is picky when generating function pointer for delegates with empty structs, leading to
// those 'mini-amd64.c condition fields not met' crashes.
if (struct_.fields.size() == 0)
{
if (!as_generator(indent << scope_tab << "/// <summary>Placeholder field</summary>\n"
<< indent << scope_tab << "public IntPtr field;\n").generate(sink, nullptr, context))
return false;
}
else
{ {
// Constructor with default parameters for easy struct initialization // Constructor with default parameters for easy struct initialization
if(!as_generator( if(!as_generator(
@ -608,9 +533,9 @@ struct struct_definition_generator
<< *(indent << scope_tab << field_argument_docs << "\n") << *(indent << scope_tab << field_argument_docs << "\n")
<< indent << scope_tab << "public " << string << "(\n" << indent << scope_tab << "public " << string << "(\n"
<< ((indent << scope_tab << scope_tab << field_argument_default) % ",\n") << ((indent << scope_tab << scope_tab << field_argument_default) % ",\n")
<< indent << scope_tab << ")\n" << ")\n"
<< indent << scope_tab << "{\n" << indent << scope_tab << "{\n"
<< *(indent << scope_tab << scope_tab << field_argument_assignment << ";\n") << *(indent << scope_tab << scope_tab << field_argument_assignment)
<< indent << scope_tab << "}\n\n") << indent << scope_tab << "}\n\n")
.generate(sink, std::make_tuple(struct_.fields, struct_name, struct_.fields, struct_.fields), context)) .generate(sink, std::make_tuple(struct_.fields, struct_name, struct_.fields, struct_.fields), context))
return false; return false;
@ -638,7 +563,14 @@ struct struct_definition_generator
).generate(sink, attributes::unused, context)) ).generate(sink, attributes::unused, context))
return false; return false;
if (struct_.fields.size() != 0 ) if (struct_.fields.size() == 1 )
{
if (!as_generator(
indent << scope_tab << scope_tab << "return " << name_helpers::managed_name(struct_.fields[0].name) << ".GetHashCode();\n"
).generate(sink, attributes::unused, context))
return false;
}
else if (struct_.fields.size() != 0 )
{ {
// int hash = 17; // int hash = 17;
// hash = 23 * fieldA.GetHashCode(); // hash = 23 * fieldA.GetHashCode();
@ -647,7 +579,7 @@ struct struct_definition_generator
// return hash // return hash
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << "int hash = 17;\n" indent << scope_tab << scope_tab << "int hash = 17;\n"
<< *(grammar::attribute_reorder<-1, -1>(indent << scope_tab << scope_tab << "hash = hash * 23 + " << name_helpers::struct_field_name << ".GetHashCode(" << culture_info << ");\n")) << *(grammar::attribute_reorder<-1, -1>(indent << scope_tab << scope_tab << "hash = hash * 23 + " << name_helpers::struct_property_name << ".GetHashCode(" << culture_info << ");\n"))
<< indent << scope_tab << scope_tab << "return hash;\n" << indent << scope_tab << scope_tab << "return hash;\n"
).generate(sink, struct_.fields, context)) ).generate(sink, struct_.fields, context))
return false; return false;
@ -656,7 +588,7 @@ struct struct_definition_generator
{ {
// Just compare the place holder pointers // Just compare the place holder pointers
if (!as_generator( if (!as_generator(
"return field.GetHashCode();\n" indent << scope_tab << scope_tab << "return field.GetHashCode();\n"
).generate(sink, attributes::unused, context)) ).generate(sink, attributes::unused, context))
return false; return false;
} }
@ -680,7 +612,7 @@ struct struct_definition_generator
if (struct_.fields.size() != 0 ) if (struct_.fields.size() != 0 )
{ {
if (!as_generator( if (!as_generator(
grammar::attribute_reorder<-1, -1>((name_helpers::struct_field_name << " == other." << name_helpers::struct_field_name)) % " && " grammar::attribute_reorder<-1, -1>((name_helpers::struct_property_name << " == other." << name_helpers::struct_property_name)) % " && "
).generate(sink, struct_.fields, context)) ).generate(sink, struct_.fields, context))
return false; return false;
} }
@ -695,7 +627,7 @@ struct struct_definition_generator
if (!as_generator( if (!as_generator(
indent << scope_tab << scope_tab << ";\n" ";\n"
<< indent << scope_tab << "}\n" << indent << scope_tab << "}\n"
).generate(sink, attributes::unused, context)) ).generate(sink, attributes::unused, context))
return false; return false;
@ -745,8 +677,7 @@ struct struct_definition_generator
<< indent << scope_tab << "/// <param name=\"ptr\">Native pointer to be converted.</param>\n" << indent << scope_tab << "/// <param name=\"ptr\">Native pointer to be converted.</param>\n"
<< indent << scope_tab << "public static implicit operator " << struct_name << "(IntPtr ptr)\n" << indent << scope_tab << "public static implicit operator " << struct_name << "(IntPtr ptr)\n"
<< indent << scope_tab << "{\n" << indent << scope_tab << "{\n"
<< indent << scope_tab << scope_tab << "var tmp = (" << struct_name << ".NativeStruct)Marshal.PtrToStructure(ptr, typeof(" << struct_name << ".NativeStruct));\n" << indent << scope_tab << scope_tab << "return (" << struct_name << ")Marshal.PtrToStructure(ptr, typeof(" << struct_name << "));\n"
<< indent << scope_tab << scope_tab << "return tmp;\n"
<< indent << scope_tab << "}\n\n" << indent << scope_tab << "}\n\n"
).generate(sink, attributes::unused, context)) ).generate(sink, attributes::unused, context))
return false; return false;
@ -771,9 +702,6 @@ struct struct_definition_generator
).generate(sink, attributes::unused, context)) ).generate(sink, attributes::unused, context))
return false; return false;
if (!struct_internal_definition.generate(sink, struct_, change_indentation(indent.inc(), context)))
return false;
if(!as_generator(indent << "}\n\n").generate(sink, attributes::unused, context)) return false; if(!as_generator(indent << "}\n\n").generate(sink, attributes::unused, context)) return false;
return true; return true;
@ -809,9 +737,9 @@ template <>
struct is_generator< ::eolian_mono::struct_definition_generator> : std::true_type {}; struct is_generator< ::eolian_mono::struct_definition_generator> : std::true_type {};
template <> template <>
struct is_eager_generator< ::eolian_mono::struct_internal_definition_generator> : std::true_type {}; struct is_eager_generator< ::eolian_mono::struct_private_property_generator> : std::true_type {};
template <> template <>
struct is_generator< ::eolian_mono::struct_internal_definition_generator> : std::true_type {}; struct is_generator< ::eolian_mono::struct_private_property_generator> : std::true_type {};
template <> template <>
struct is_eager_generator< ::eolian_mono::to_internal_field_convert_generator> : std::true_type {}; struct is_eager_generator< ::eolian_mono::to_internal_field_convert_generator> : std::true_type {};
@ -833,7 +761,7 @@ template <>
struct attributes_needed< ::eolian_mono::struct_definition_generator> : std::integral_constant<int, 1> {}; struct attributes_needed< ::eolian_mono::struct_definition_generator> : std::integral_constant<int, 1> {};
template <> template <>
struct attributes_needed< ::eolian_mono::struct_internal_definition_generator> : std::integral_constant<int, 1> {}; struct attributes_needed< ::eolian_mono::struct_private_property_generator> : std::integral_constant<int, 1> {};
template <> template <>
struct attributes_needed< ::eolian_mono::to_internal_field_convert_generator> : std::integral_constant<int, 1> {}; struct attributes_needed< ::eolian_mono::to_internal_field_convert_generator> : std::integral_constant<int, 1> {};

View File

@ -69,11 +69,121 @@ struct field_argument_assignment_generator
template<typename OutputIterator, typename Context> template<typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const
{ {
auto field_name = name_helpers::to_field_name(field.name); auto field_name = to_field_name(field.name);
if (!as_generator("this." << field_name << " = " << field_name) // FIXME Replace need_struct_conversion(regular) with need_struct_conversion(type)
.generate(sink, attributes::unused, context)) auto regular = efl::eina::get<attributes::regular_type_def>(&field.type.original_type);
return false; auto klass = efl::eina::get<attributes::klass_name>(&field.type.original_type);
return true; auto complex = efl::eina::get<attributes::complex_type_def>(&field.type.original_type);
if (klass)
{
if (!as_generator(
"this." << string << " = " << string << "?.NativeHandle ?? System.IntPtr.Zero;\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if ((complex && (complex->outer.base_type == "array")))
{
if (!as_generator(
"this." << string << " = Efl.Eo.Globals.IListToNativeArray(" << string << ", " << (field.type.has_own ? "true" : "false") << ");\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if ((complex && (complex->outer.base_type == "list")))
{
if (!as_generator(
"this." << string << " = Efl.Eo.Globals.IListToNativeList(" << string << ", " << (field.type.has_own ? "true" : "false") << ");\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if ((complex && (complex->outer.base_type == "iterator")))
{
if (!as_generator(
"this." << string << " = Efl.Eo.Globals.IEnumerableToIterator(" << string << ", " << (field.type.has_own ? "true" : "false") << ");\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if ((complex && (complex->outer.base_type == "hash"))
|| field.type.c_type == "Eina_Binbuf *" || field.type.c_type == "const Eina_Binbuf *")
{
// Always assumes pointer
if (!as_generator(
"this." << string << " = " << string << ".Handle;\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if (field.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular))
{
if (!as_generator(
"this." << string << " = Eina.PrimitiveConversion.ManagedToPointerAlloc(" << string << ");\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if (helpers::need_struct_conversion(regular))
{
if (!as_generator(
"this." << string << " = " << string << ";\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if (regular && (regular->base_type == "string" || regular->base_type == "mstring"))
{
if (!as_generator(
"this." << string << " = Eina.MemoryNative.StrDup(" << string << ");\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if (regular && regular->base_type == "stringshare")
{
if (!as_generator(
"this." << string << " = Eina.MemoryNative.AddStringshare(" << string << ");\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if (field.type.c_type == "Eina_Slice" || field.type.c_type == "const Eina_Slice"
|| field.type.c_type == "Eina_Rw_Slice" || field.type.c_type == "const Eina_Rw_Slice")
{
if (!as_generator(
"this." << string << " = " << string << ";\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if (field.type.c_type == "Eina_Value" || field.type.c_type == "const Eina_Value")
{
if (!as_generator(
"this." << string << " = " << string << ".GetNative();\n"
).generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *")
{
if (!as_generator(
"this." << string << " = " << string << "?.NativeHandle ?? System.IntPtr.Zero;\n"
).generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if (!field.type.is_ptr && regular && regular->base_type == "bool")
{
if (!as_generator(
"this." << string << " = " << string << " ? (byte)1 : (byte)0;\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if (!field.type.is_ptr && regular && regular->base_type == "char")
{
if (!as_generator(
"this." << string << " = (byte)" << string << ";\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else // primitives and enums
{
if (!as_generator(
"this." << string << " = " << string << ";\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
return true;
} }
} const field_argument_assignment {}; } const field_argument_assignment {};

View File

@ -90,6 +90,28 @@ namespace eolian_mono { namespace utils {
return ret; return ret;
} }
std::string to_camel_case(const std::vector<std::string> &names, std::string const& delim="")
{
std::vector<std::string> outv(names.size());
std::stringstream osstream;
std::transform(names.begin(), names.end(), outv.begin(),
[](std::string name) {
name[0] = std::toupper(name[0]);
return name;
});
std::copy(outv.begin(), outv.end(), std::ostream_iterator<std::string>(osstream, delim.c_str()));
std::string ret = osstream.str();
if (delim != "")
ret.pop_back(); // We could implement an infix_iterator but this pop is enough for now.
ret[0] = std::tolower(ret[0]);
return ret;
}
inline std::string remove_all(std::string name, char target) inline std::string remove_all(std::string name, char target)
{ {
name.erase(std::remove(name.begin(), name.end(), target), name.end()); name.erase(std::remove(name.begin(), name.end(), target), name.end());

View File

@ -328,7 +328,7 @@ public abstract class EoWrapper : IWrapper, IDisposable
internal Efl.EventCb GetInternalEventCallback<T>(EventHandler<T> handler, Func<IntPtr, T> createArgsInstance) where T:EventArgs internal Efl.EventCb GetInternalEventCallback<T>(EventHandler<T> handler, Func<IntPtr, T> createArgsInstance) where T:EventArgs
{ {
return (IntPtr data, ref Efl.Event.NativeStruct evt) => return (IntPtr data, ref Efl.Event evt) =>
{ {
var obj = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data).Target; var obj = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data).Target;
if (obj != null) if (obj != null)
@ -348,7 +348,7 @@ public abstract class EoWrapper : IWrapper, IDisposable
internal Efl.EventCb GetInternalEventCallback(EventHandler handler) internal Efl.EventCb GetInternalEventCallback(EventHandler handler)
{ {
return (IntPtr data, ref Efl.Event.NativeStruct evt) => return (IntPtr data, ref Efl.Event evt) =>
{ {
var obj = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data).Target; var obj = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data).Target;
if (obj != null) if (obj != null)
@ -383,13 +383,13 @@ public abstract class EoWrapper : IWrapper, IDisposable
} }
} }
private static void OwnershipUniqueCallback(IntPtr data, ref Efl.Event.NativeStruct evt) private static void OwnershipUniqueCallback(IntPtr data, ref Efl.Event evt)
{ {
var ws = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data); var ws = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data);
ws.MakeUnique(); ws.MakeUnique();
} }
private static void OwnershipSharedCallback(IntPtr data, ref Efl.Event.NativeStruct evt) private static void OwnershipSharedCallback(IntPtr data, ref Efl.Event evt)
{ {
var ws = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data); var ws = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data);
ws.MakeShared(); ws.MakeShared();

View File

@ -173,17 +173,24 @@ internal struct EventDescription
[Efl.Eo.BindingEntity] [Efl.Eo.BindingEntity]
internal struct Event internal struct Event
{ {
/// <summary>Internal wrapper for field Object</summary>
private System.IntPtr obj;
/// <summary>Internal wrapper for field Desc</summary>
private System.IntPtr desc;
/// <summary>Internal wrapper for field Info</summary>
private System.IntPtr info;
/// <summary> /// <summary>
/// The object the callback was called on. /// The object the callback was called on.
/// <para>Since EFL 1.22.</para> /// <para>Since EFL 1.22.</para>
/// </summary> /// </summary>
public Efl.Object Object; public Efl.Object Object { get => (Efl.Object) Efl.Eo.Globals.CreateWrapperFor(obj); }
/// <summary> /// <summary>
/// The event description. /// The event description.
/// <para>Since EFL 1.22.</para> /// <para>Since EFL 1.22.</para>
/// </summary> /// </summary>
public Efl.EventDescription Desc; public Efl.EventDescription Desc { get => Eina.PrimitiveConversion.PointerToManaged<Efl.EventDescription>(desc); }
/// <summary> /// <summary>
/// Extra event information passed by the event caller. /// Extra event information passed by the event caller.
@ -192,7 +199,7 @@ internal struct Event
/// 2) Structs, built-in types and containers are passed as const pointers, with one level of indirection. /// 2) Structs, built-in types and containers are passed as const pointers, with one level of indirection.
/// <para>Since EFL 1.22.</para> /// <para>Since EFL 1.22.</para>
/// </summary> /// </summary>
public System.IntPtr Info; public System.IntPtr Info { get => info; }
/// <summary>Constructor for Event.</summary> /// <summary>Constructor for Event.</summary>
public Event( public Event(
@ -200,59 +207,21 @@ internal struct Event
Efl.EventDescription desc = default(Efl.EventDescription), Efl.EventDescription desc = default(Efl.EventDescription),
System.IntPtr info = default(System.IntPtr)) System.IntPtr info = default(System.IntPtr))
{ {
this.Object = obj; this.obj = obj?.NativeHandle ?? System.IntPtr.Zero;
this.Desc = desc; this.desc = Eina.PrimitiveConversion.ManagedToPointerAlloc(desc);
this.Info = info; this.info = info;
} }
/// <summary>Implicit conversion to the managed representation from a native pointer.</summary> /// <summary>Implicit conversion to the managed representation from a native pointer.</summary>
/// <param name="ptr">Native pointer to be converted.</param> /// <param name="ptr">Native pointer to be converted.</param>
public static implicit operator Event(IntPtr ptr) public static implicit operator Event(IntPtr ptr)
{ {
var tmp = (Event.NativeStruct) Marshal.PtrToStructure(ptr, typeof(Event.NativeStruct)); var tmp = (Event) Marshal.PtrToStructure(ptr, typeof(Event));
return tmp; return tmp;
} }
/// <summary>Internal wrapper for struct Event.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct NativeStruct
{
/// <summary>Internal wrapper for field Object</summary>
public System.IntPtr Object;
/// <summary>Internal wrapper for field Desc</summary>
public System.IntPtr Desc;
/// <summary>Internal wrapper for field Info</summary>
public System.IntPtr Info;
/// <summary>Implicit conversion to the internal/marshalling representation.</summary>
/// <param name="externalStruct">Managed struct to be converted.</param>
/// <returns>Native representation of the managed struct.</returns>
public static implicit operator Event.NativeStruct(Event externalStruct)
{
var internalStruct = new Event.NativeStruct();
internalStruct.Object = externalStruct.Object?.NativeHandle ?? System.IntPtr.Zero;
internalStruct.Desc = Eina.PrimitiveConversion.ManagedToPointerAlloc(externalStruct.Desc);
internalStruct.Info = externalStruct.Info;
return internalStruct;
}
/// <summary>Implicit conversion to the managed representation.</summary>
/// <param name="internalStruct">Native struct to be converted.</param>
/// <returns>Managed representation of the native struct.</returns>
public static implicit operator Event(Event.NativeStruct internalStruct)
{
var externalStruct = new Event();
externalStruct.Object = (Efl.Object) Efl.Eo.Globals.CreateWrapperFor(internalStruct.Object);
externalStruct.Desc = Eina.PrimitiveConversion.PointerToManaged<Efl.EventDescription>(internalStruct.Desc);
externalStruct.Info = internalStruct.Info;
return externalStruct;
}
}
} }
internal delegate void EventCb(System.IntPtr data, ref Event.NativeStruct evt); internal delegate void EventCb(System.IntPtr data, ref Event evt);
internal delegate void FreeWrapperSupervisorCb(System.IntPtr obj); internal delegate void FreeWrapperSupervisorCb(System.IntPtr obj);
namespace Access namespace Access

View File

@ -196,8 +196,7 @@ class TestEoEvents
received_struct = e.arg; received_struct = e.arg;
}; };
Dummy.StructSimple sent_struct = default(Dummy.StructSimple); Dummy.StructSimple sent_struct = new Dummy.StructSimple(fstring: "Struct Event");
sent_struct.Fstring = "Struct Event";
obj.EmitEventWithStruct(sent_struct); obj.EmitEventWithStruct(sent_struct);

View File

@ -30,40 +30,38 @@ internal class StructHelpers
internal static Dummy.StructSimple structSimpleWithValues() internal static Dummy.StructSimple structSimpleWithValues()
{ {
var simple = new Dummy.StructSimple(); return new Dummy.StructSimple(
fbyte: (sbyte)-126,
simple.Fbyte = (sbyte)-126; fubyte: (byte) 254u,
simple.Fubyte = (byte) 254u; fchar: '~',
simple.Fchar = '~'; fshort: (short) -32766,
simple.Fshort = (short) -32766; fushort: (ushort) 65534u,
simple.Fushort = (ushort) 65534u; fint: -32766,
simple.Fint = -32766; fuint: 65534u,
simple.Fuint = 65534u; flong: -2147483646,
simple.Flong = -2147483646; fulong: 4294967294u,
simple.Fulong = 4294967294u; fllong: -9223372036854775806,
simple.Fllong = -9223372036854775806; fullong: 18446744073709551614u,
simple.Fullong = 18446744073709551614u; fint8: (sbyte) -126,
simple.Fint8 = (sbyte) -126; fuint8: (byte) 254u,
simple.Fuint8 = (byte) 254u; fint16: (short) -32766,
simple.Fint16 = (short) -32766; fuint16: (ushort) 65534u,
simple.Fuint16 = (ushort) 65534u; fint32: -2147483646,
simple.Fint32 = -2147483646; fuint32: 4294967294u,
simple.Fuint32 = 4294967294u; fint64: -9223372036854775806,
simple.Fint64 = -9223372036854775806; fuint64: 18446744073709551614u,
simple.Fuint64 = 18446744073709551614u; fssize: -2147483646,
simple.Fssize = -2147483646; fsize: 4294967294u,
simple.Fsize = 4294967294u; fintptr: (IntPtr) 0xFE,
simple.Fintptr = (IntPtr) 0xFE; fptrdiff: -2147483646,
simple.Fptrdiff = -2147483646; ffloat: -16777216.0f,
simple.Ffloat = -16777216.0f; fdouble: -9007199254740992.0,
simple.Fdouble = -9007199254740992.0; fbool: true,
simple.Fbool = true; fenum: Dummy.SampleEnum.V2,
simple.Fenum = Dummy.SampleEnum.V2; fstring: "test/string",
simple.Fstring = "test/string"; fmstring: "test/mstring",
simple.Fmstring = "test/mstring"; fstringshare: "test/stringshare"
simple.Fstringshare = "test/stringshare"; );
return simple;
} }
internal static void checkStructSimple(Dummy.StructSimple simple) internal static void checkStructSimple(Dummy.StructSimple simple)
@ -137,42 +135,41 @@ internal class StructHelpers
#if EFL_BETA #if EFL_BETA
internal static Dummy.StructComplex structComplexWithValues() internal static Dummy.StructComplex structComplexWithValues()
{ {
var complex = new Dummy.StructComplex(); var Farray = new Eina.Array<string>();
Farray.Add("0x0");
Farray.Add("0x2A");
Farray.Add("0x42");
complex.Farray = new Eina.Array<string>(); var Flist = new Eina.List<string>();
complex.Farray.Add("0x0"); Flist.Add("0x0");
complex.Farray.Add("0x2A"); Flist.Add("0x2A");
complex.Farray.Add("0x42"); Flist.Add("0x42");
complex.Flist = new Eina.List<string>(); var Fhash = new Eina.Hash<string, string>();
complex.Flist.Add("0x0"); Fhash["aa"] = "aaa";
complex.Flist.Add("0x2A"); Fhash["bb"] = "bbb";
complex.Flist.Add("0x42"); Fhash["cc"] = "ccc";
complex.Fhash = new Eina.Hash<string, string>(); var Fiterator = ((Eina.Array<string>)Farray).GetIterator();
complex.Fhash["aa"] = "aaa";
complex.Fhash["bb"] = "bbb";
complex.Fhash["cc"] = "ccc";
complex.Fiterator = ((Eina.Array<string>)complex.Farray).GetIterator(); var Fany_value = new Eina.Value(Eina.ValueType.Double);
Fany_value.Set(-9007199254740992.0);
complex.Fany_value = new Eina.Value(Eina.ValueType.Double); var Fany_value_ref = new Eina.Value(Eina.ValueType.String);
complex.Fany_value.Set(-9007199254740992.0); Fany_value_ref.Set("abc");
complex.Fany_value_ref = new Eina.Value(Eina.ValueType.String); var Fbinbuf = new Eina.Binbuf();
complex.Fany_value_ref.Set("abc"); Fbinbuf.Append(126);
complex.Fbinbuf = new Eina.Binbuf(); var Fslice = new Eina.Slice(Eina.MemoryNative.Alloc(1), (UIntPtr)1);
complex.Fbinbuf.Append(126); Marshal.WriteByte(Fslice.Mem, 125);
complex.Fslice.Length = 1; var Fobj = new Dummy.Numberwrapper();
complex.Fslice.Mem = Eina.MemoryNative.Alloc(1); Fobj.SetNumber(42);
Marshal.WriteByte(complex.Fslice.Mem, 125);
complex.Fobj = new Dummy.Numberwrapper(); return new Dummy.StructComplex(farray: Farray, flist: Flist, fhash: Fhash,
complex.Fobj.SetNumber(42); fiterator: Fiterator, fanyValue:Fany_value, fanyValueRef: Fany_value_ref,
fbinbuf: Fbinbuf, fslice:Fslice, fobj: Fobj);
return complex;
} }
internal static void checkStructComplex(Dummy.StructComplex complex) internal static void checkStructComplex(Dummy.StructComplex complex)
@ -194,11 +191,11 @@ internal class StructHelpers
Test.AssertEquals(idx, base_seq_str.Length); Test.AssertEquals(idx, base_seq_str.Length);
double double_val = 0; double double_val = 0;
Test.Assert(complex.Fany_value.Get(out double_val)); Test.Assert(complex.FanyValue.Get(out double_val));
Test.Assert(double_val == -9007199254740992.0); Test.Assert(double_val == -9007199254740992.0);
string str_val = null; string str_val = null;
Test.Assert(complex.Fany_value_ref.Get(out str_val)); Test.Assert(complex.FanyValueRef.Get(out str_val));
Test.Assert(str_val == "abc"); Test.Assert(str_val == "abc");
Test.Assert(complex.Fbinbuf.Length == 1); Test.Assert(complex.Fbinbuf.Length == 1);
@ -218,8 +215,8 @@ internal class StructHelpers
Test.Assert(complex.Flist == null); Test.Assert(complex.Flist == null);
Test.Assert(complex.Fhash == null); Test.Assert(complex.Fhash == null);
Test.Assert(complex.Fiterator == null); Test.Assert(complex.Fiterator == null);
Test.Assert(complex.Fany_value == null); Test.Assert(complex.FanyValue == null);
Test.Assert(complex.Fany_value_ref == null); Test.Assert(complex.FanyValueRef == null);
Test.Assert(complex.Fbinbuf == null); Test.Assert(complex.Fbinbuf == null);
Test.Assert(complex.Fslice.Length == 0); Test.Assert(complex.Fslice.Length == 0);

View File

@ -180,8 +180,7 @@ internal class TestStructs
public override bool StructSimpleOut(out Dummy.StructSimple simple) { public override bool StructSimpleOut(out Dummy.StructSimple simple) {
called = true; called = true;
simple = new Dummy.StructSimple(); simple = new Dummy.StructSimple(fstring: "Virtual Struct Out");
simple.Fstring = "Virtual Struct Out";
return true; return true;
} }
@ -206,8 +205,7 @@ internal class TestStructs
public override Dummy.StructSimple StructSimpleReturn() public override Dummy.StructSimple StructSimpleReturn()
{ {
called = true; called = true;
var simple = new Dummy.StructSimple(); var simple = new Dummy.StructSimple(fstring: "Virtual Struct Return");
simple.Fstring = "Virtual Struct Return";
return simple; return simple;
} }
@ -234,7 +232,6 @@ internal class TestStructs
{ {
StructReturner t = new StructReturner(); StructReturner t = new StructReturner();
var simple = structSimpleWithValues(); var simple = structSimpleWithValues();
simple.Fstring = "Virtual Struct In";
t.CallStructSimpleIn(simple); t.CallStructSimpleIn(simple);
Test.Assert(t.called); Test.Assert(t.called);
@ -379,13 +376,13 @@ internal class TestStructs
internal class TestStructEquality internal class TestStructEquality
{ {
static Dummy.StructSimple a = new Dummy.StructSimple(1, 2, (char)3, 4, Fstring: "", Fmstring: "", Fstringshare: ""); static Dummy.StructSimple a = new Dummy.StructSimple(1, 2, (char)3, 4, fstring: "", fmstring: "", fstringshare: "");
static Dummy.StructSimple b = new Dummy.StructSimple(1, 2, (char)3, 4, Fstring: "", Fmstring: "", Fstringshare: ""); static Dummy.StructSimple b = new Dummy.StructSimple(1, 2, (char)3, 4, fstring: "", fmstring: "", fstringshare: "");
static Dummy.StructSimple c = new Dummy.StructSimple(4, 3, (char)2, 1, Fstring: "", Fmstring: "", Fstringshare: ""); static Dummy.StructSimple c = new Dummy.StructSimple(4, 3, (char)2, 1, fstring: "", fmstring: "", fstringshare: "");
// to check if we differ on a single struct field // to check if we differ on a single struct field
static Dummy.StructSimple singleDifferentField = new Dummy.StructSimple(1, 2, (char)3, 5, Fstring: "", Fmstring: "", Fstringshare: ""); static Dummy.StructSimple singleDifferentField = new Dummy.StructSimple(1, 2, (char)3, 5, fstring: "", fmstring: "", fstringshare: "");
public static void test_equals() public static void test_equals()
{ {