summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYeongjong Lee <yj34.lee@samsung.com>2020-01-28 14:46:10 +0900
committerWooHyun Jung <wh0705.jung@samsung.com>2020-01-28 14:46:10 +0900
commit581bec9598943cc9274dfe7db1a73a4c878c3cdd (patch)
treeae52675a45025659459dfb329e73538417dc625f
parentb3c0da13d80456bcbf3954698413df5ee845b8c2 (diff)
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
-rw-r--r--src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh4
-rw-r--r--src/bin/eolian_mono/eolian/mono/name_helpers.hh20
-rw-r--r--src/bin/eolian_mono/eolian/mono/struct_definition.hh212
-rw-r--r--src/bin/eolian_mono/eolian/mono/struct_fields.hh120
-rw-r--r--src/bin/eolian_mono/eolian/mono/utils.hh22
-rw-r--r--src/bindings/mono/eo_mono/EoWrapper.cs8
-rw-r--r--src/bindings/mono/eo_mono/workaround.cs61
-rw-r--r--src/tests/efl_mono/Events.cs3
-rw-r--r--src/tests/efl_mono/StructHelpers.cs127
-rw-r--r--src/tests/efl_mono/Structs.cs15
10 files changed, 316 insertions, 276 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh b/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh
index 4d1e188997..60b495ea39 100644
--- a/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh
+++ b/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh
@@ -129,7 +129,7 @@ struct marshall_type_visitor_generate
129 , {"event", nullptr, [&] 129 , {"event", nullptr, [&]
130 { 130 {
131 regular_type_def r = regular; 131 regular_type_def r = regular;
132 r.base_type = "Efl.Event.NativeStruct"; 132 r.base_type = "Efl.Event";
133 r.namespaces.clear(); 133 r.namespaces.clear();
134 return r; 134 return r;
135 }} 135 }}
@@ -190,7 +190,7 @@ struct marshall_type_visitor_generate
190 { 190 {
191 if ((is_out || is_return) && is_ptr) 191 if ((is_out || is_return) && is_ptr)
192 return as_generator("System.IntPtr").generate(sink, attributes::unused, *context); 192 return as_generator("System.IntPtr").generate(sink, attributes::unused, *context);
193 return as_generator(string << ".NativeStruct") 193 return as_generator(string)
194 .generate(sink, name_helpers::type_full_managed_name(regular), *context); 194 .generate(sink, name_helpers::type_full_managed_name(regular), *context);
195 } 195 }
196 else if (eina::optional<bool> b = type_match::get_match 196 else if (eina::optional<bool> b = type_match::get_match
diff --git a/src/bin/eolian_mono/eolian/mono/name_helpers.hh b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
index ae958ba623..a6e94ea2f6 100644
--- a/src/bin/eolian_mono/eolian/mono/name_helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
@@ -331,7 +331,8 @@ inline std::string enum_field_managed_name(std::string name)
331 331
332inline std::string to_field_name(std::string const& in) 332inline std::string to_field_name(std::string const& in)
333{ 333{
334 return utils::capitalize(in); 334 std::vector<std::string> names = utils::split(in, '_');
335 return utils::to_camel_case(names);
335} 336}
336 337
337 338
@@ -583,6 +584,16 @@ struct struct_field_name_generator
583 } 584 }
584} const struct_field_name {}; 585} const struct_field_name {};
585 586
587// Property names //
588struct struct_property_name_generator
589{
590 template <typename OutputIterator, typename Context>
591 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const
592 {
593 return as_generator(string).generate(sink, name_helpers::managed_name(field.name), context);
594 }
595} const struct_property_name {};
596
586} // namespace name_helpers 597} // namespace name_helpers
587 598
588} // namespace eolian_mono 599} // namespace eolian_mono
@@ -615,12 +626,19 @@ struct is_eager_generator<eolian_mono::name_helpers::struct_field_name_generator
615template <> 626template <>
616struct is_generator< ::eolian_mono::name_helpers::struct_field_name_generator> : std::true_type {}; 627struct is_generator< ::eolian_mono::name_helpers::struct_field_name_generator> : std::true_type {};
617 628
629template <>
630struct is_eager_generator<eolian_mono::name_helpers::struct_property_name_generator> : std::true_type {};
631template <>
632struct is_generator< ::eolian_mono::name_helpers::struct_property_name_generator> : std::true_type {};
633
618namespace type_traits { 634namespace type_traits {
619template <> 635template <>
620struct attributes_needed<struct ::eolian_mono::name_helpers::klass_full_concrete_or_interface_name_generator> : std::integral_constant<int, 1> {}; 636struct attributes_needed<struct ::eolian_mono::name_helpers::klass_full_concrete_or_interface_name_generator> : std::integral_constant<int, 1> {};
621 637
622template <> 638template <>
623struct attributes_needed< ::eolian_mono::name_helpers::struct_field_name_generator> : std::integral_constant<int, 1> {}; 639struct attributes_needed< ::eolian_mono::name_helpers::struct_field_name_generator> : std::integral_constant<int, 1> {};
640template <>
641struct attributes_needed< ::eolian_mono::name_helpers::struct_property_name_generator> : std::integral_constant<int, 1> {};
624 642
625} 643}
626 644
diff --git a/src/bin/eolian_mono/eolian/mono/struct_definition.hh b/src/bin/eolian_mono/eolian/mono/struct_definition.hh
index 48d69dc834..6f19088d52 100644
--- a/src/bin/eolian_mono/eolian/mono/struct_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/struct_definition.hh
@@ -181,7 +181,6 @@ struct to_external_field_convert_generator
181 template <typename OutputIterator, typename Context> 181 template <typename OutputIterator, typename Context>
182 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const 182 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const
183 { 183 {
184 auto const& indent = current_indentation(context);
185 auto field_name = name_helpers::to_field_name(field.name); 184 auto field_name = name_helpers::to_field_name(field.name);
186 auto regular = efl::eina::get<attributes::regular_type_def>(&field.type.original_type); 185 auto regular = efl::eina::get<attributes::regular_type_def>(&field.type.original_type);
187 auto klass = efl::eina::get<attributes::klass_name>(&field.type.original_type); 186 auto klass = efl::eina::get<attributes::klass_name>(&field.type.original_type);
@@ -191,113 +190,108 @@ struct to_external_field_convert_generator
191 { 190 {
192 auto interface_name = name_helpers::klass_full_interface_name(*klass); 191 auto interface_name = name_helpers::klass_full_interface_name(*klass);
193 if (!as_generator( 192 if (!as_generator(
194 "\n" 193 "(" << interface_name << ") Efl.Eo.Globals.CreateWrapperFor(" << string << ");"
195 << indent << scope_tab << scope_tab << "_external_struct." << string
196 << " = (" << interface_name << ") Efl.Eo.Globals.CreateWrapperFor(_internal_struct." << string << ");\n"
197 ).generate(sink, std::make_tuple(field_name, field_name), context)) 194 ).generate(sink, std::make_tuple(field_name, field_name), context))
198 return false; 195 return false;
199 } 196 }
200 else if (field.type.c_type == "Eina_Binbuf *" || field.type.c_type == "const Eina_Binbuf *") 197 else if (field.type.c_type == "Eina_Binbuf *" || field.type.c_type == "const Eina_Binbuf *")
201 { 198 {
202 if (!as_generator( 199 if (!as_generator(
203 indent << scope_tab << scope_tab << "_external_struct." << string << " = new " << type << "(_internal_struct." << string << ", false);\n") 200 "new " << type << "(" << string << ", false);")
204 .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) 201 .generate(sink, std::make_tuple(field.type, field_name), context))
205 return false; 202 return false;
206 } 203 }
207 else if (complex && (complex->outer.base_type == "array")) 204 else if (complex && (complex->outer.base_type == "array"))
208 { 205 {
209 // Always assumes pointer 206 // Always assumes pointer
210 if (!as_generator( 207 if (!as_generator(
211 indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.Globals.NativeArrayTo" << type << "(_internal_struct." << string << ");\n") 208 "Efl.Eo.Globals.NativeArrayTo" << type << "(" << string << ");")
212 .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) 209 .generate(sink, std::make_tuple(field.type, field_name), context))
213 return false; 210 return false;
214 } 211 }
215 else if (complex && (complex->outer.base_type == "list")) 212 else if (complex && (complex->outer.base_type == "list"))
216 { 213 {
217 // Always assumes pointer 214 // Always assumes pointer
218 if (!as_generator( 215 if (!as_generator(
219 indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.Globals.NativeListTo" << type << "(_internal_struct." << string << ");\n") 216 "Efl.Eo.Globals.NativeListTo" << type << "(" << string << ");")
220 .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) 217 .generate(sink, std::make_tuple(field.type, field_name), context))
221 return false; 218 return false;
222 } 219 }
223 else if (complex && complex->outer.base_type == "hash") 220 else if (complex && complex->outer.base_type == "hash")
224 { 221 {
225 if (!as_generator( 222 if (!as_generator(
226 indent << scope_tab << scope_tab << "_external_struct." << string << " = new " << type << "(_internal_struct." << string << ", false, false, false);\n") 223 "new " << type << "(" << string << ", false, false, false);")
227 .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) 224 .generate(sink, std::make_tuple(field.type, field_name), context))
228 return false; 225 return false;
229 } 226 }
230 else if (complex && complex->outer.base_type == "iterator") 227 else if (complex && complex->outer.base_type == "iterator")
231 { 228 {
232 if (!as_generator( 229 if (!as_generator(
233 indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.Globals.IteratorTo" << type << "(_internal_struct." << string << ");\n") 230 "Efl.Eo.Globals.IteratorTo" << type << "(" << string << ");")
234 .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) 231 .generate(sink, std::make_tuple(field.type, field_name), context))
235 return false; 232 return false;
236 } 233 }
237 else if (field.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular)) 234 else if (field.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular))
238 { 235 {
239 if (!as_generator( 236 if (!as_generator(
240 indent << scope_tab << scope_tab << "_external_struct." << string << " = Eina.PrimitiveConversion.PointerToManaged<" << type << ">(_internal_struct." << string << ");\n") 237 "Eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << string << ");")
241 .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) 238 .generate(sink, std::make_tuple(field.type, field_name), context))
242 return false; 239 return false;
243 } 240 }
244 else if (helpers::need_struct_conversion(regular)) 241 else if (helpers::need_struct_conversion(regular))
245 { 242 {
246 if (!as_generator( 243 if (!as_generator(
247 indent << scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << ";\n") 244 string << ";")
248 .generate(sink, std::make_tuple(field_name, field_name), context)) 245 .generate(sink, field_name, context))
249 return false; 246 return false;
250 } 247 }
251 else if (regular && (regular->base_type == "string" || regular->base_type == "mstring" || regular->base_type == "stringshare")) 248 else if (regular && (regular->base_type == "string" || regular->base_type == "mstring" || regular->base_type == "stringshare"))
252 { 249 {
253 if (!as_generator( 250 if (!as_generator(
254 indent << scope_tab << scope_tab << "_external_struct." << string << " = Eina.StringConversion.NativeUtf8ToManagedString(_internal_struct." << string << ");\n") 251 "Eina.StringConversion.NativeUtf8ToManagedString(" << string << ");")
255 .generate(sink, std::make_tuple(field_name, field_name), context)) 252 .generate(sink, std::make_tuple(field_name, field_name), context))
256 return false; 253 return false;
257 } 254 }
258 else if (field.type.c_type == "Eina_Slice" || field.type.c_type == "const Eina_Slice" 255 else if (field.type.c_type == "Eina_Slice" || field.type.c_type == "const Eina_Slice"
259 || field.type.c_type == "Eina_Rw_Slice" || field.type.c_type == "const Eina_Rw_Slice") 256 || field.type.c_type == "Eina_Rw_Slice" || field.type.c_type == "const Eina_Rw_Slice")
260 { 257 {
261 if (!as_generator( 258 if (!as_generator(field_name << ";")
262 "\n" <<
263 indent << scope_tab << scope_tab << "_external_struct." << field_name << ".Len = _internal_struct." << field_name << ".Len;\n" <<
264 indent << scope_tab << scope_tab << "_external_struct." << field_name << ".Mem = _internal_struct." << field_name << ".Mem;\n")
265 .generate(sink, attributes::unused, context)) 259 .generate(sink, attributes::unused, context))
266 return false; 260 return false;
267 } 261 }
268 else if (field.type.c_type == "Eina_Value" || field.type.c_type == "const Eina_Value") 262 else if (field.type.c_type == "Eina_Value" || field.type.c_type == "const Eina_Value")
269 { 263 {
270 if (!as_generator( 264 if (!as_generator(
271 indent << scope_tab << scope_tab << "_external_struct." << string << " = new Eina.Value(_internal_struct." << string << ");\n" 265 "new Eina.Value(" << string << ");"
272 ).generate(sink, std::make_tuple(field_name, field_name), context)) 266 ).generate(sink, std::make_tuple(field_name), context))
273 return false; 267 return false;
274 } 268 }
275 else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *") 269 else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *")
276 { 270 {
277 if (!as_generator( 271 if (!as_generator(
278 indent << scope_tab << scope_tab << "_external_struct." << string << " = new Eina.Value(_internal_struct." << string << ", Eina.Ownership.Unmanaged);\n" 272 "new Eina.Value(" << string << ", Eina.Ownership.Unmanaged);"
279 ).generate(sink, std::make_tuple(field_name, field_name), context)) 273 ).generate(sink, std::make_tuple(field_name), context))
280 return false; 274 return false;
281 } 275 }
282 else if (!field.type.is_ptr && regular && regular->base_type == "bool") 276 else if (!field.type.is_ptr && regular && regular->base_type == "bool")
283 { 277 {
284 if (!as_generator( 278 if (!as_generator(
285 indent << scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << " != 0;\n" 279 string << " != 0;"
286 ).generate(sink, std::make_tuple(field_name, field_name), context)) 280 ).generate(sink, std::make_tuple(field_name), context))
287 return false; 281 return false;
288 } 282 }
289 else if (!field.type.is_ptr && regular && regular->base_type == "char") 283 else if (!field.type.is_ptr && regular && regular->base_type == "char")
290 { 284 {
291 if (!as_generator( 285 if (!as_generator(
292 indent << scope_tab << scope_tab << "_external_struct." << string << " = (char)_internal_struct." << string << ";\n" 286 "(char)" << string << ";"
293 ).generate(sink, std::make_tuple(field_name, field_name), context)) 287 ).generate(sink, std::make_tuple(field_name), context))
294 return false; 288 return false;
295 } 289 }
296 else // primitives and enums 290 else // primitives and enums
297 { 291 {
298 if (!as_generator( 292 if (!as_generator(
299 indent << scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << ";\n") 293 field_name << ";"
300 .generate(sink, std::make_tuple(field_name, field_name), context)) 294 ).generate(sink, attributes::unused, context))
301 return false; 295 return false;
302 } 296 }
303 return true; 297 return true;
@@ -306,22 +300,12 @@ struct to_external_field_convert_generator
306 300
307// Internal Struct // 301// Internal Struct //
308 302
309struct struct_internal_definition_generator 303struct struct_private_property_generator
310{ 304{
311 template <typename OutputIterator, typename Context> 305 template <typename OutputIterator, typename Context>
312 bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const 306 bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const
313 { 307 {
314 auto const& indent = current_indentation(context); 308 auto const& indent = current_indentation(context);
315 if (!as_generator
316 (
317 "#pragma warning disable CS1591\n\n"
318 << indent << "/// <summary>Internal wrapper for struct " << string << ".</summary>\n"
319 << indent << "[StructLayout(LayoutKind.Sequential)]\n"
320 << indent << "internal struct " << string << "\n"
321 << indent << "{\n"
322 )
323 .generate(sink, std::make_tuple<>(binding_struct_name(struct_), struct_internal_decl_name()), context))
324 return false;
325 309
326 // iterate struct fields 310 // iterate struct fields
327 for (auto const& field : struct_.fields) 311 for (auto const& field : struct_.fields)
@@ -337,7 +321,7 @@ struct struct_internal_definition_generator
337 || regular->base_type == "any_value_ref"))) 321 || regular->base_type == "any_value_ref")))
338 { 322 {
339 if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n" 323 if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n"
340 << indent << scope_tab << "public System.IntPtr " << field_name << ";\n") 324 << indent << scope_tab << "private System.IntPtr " << field_name << ";\n")
341 .generate(sink, nullptr, context)) 325 .generate(sink, nullptr, context))
342 return false; 326 return false;
343 } 327 }
@@ -345,7 +329,7 @@ struct struct_internal_definition_generator
345 && regular->base_type == "bool") 329 && regular->base_type == "bool")
346 { 330 {
347 if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n" 331 if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n"
348 << indent << scope_tab << "public System.Byte " << field_name << ";\n") 332 << indent << scope_tab << "private System.Byte " << field_name << ";\n")
349 .generate(sink, nullptr, context)) 333 .generate(sink, nullptr, context))
350 return false; 334 return false;
351 } 335 }
@@ -353,12 +337,12 @@ struct struct_internal_definition_generator
353 && regular->base_type == "char") 337 && regular->base_type == "char")
354 { 338 {
355 if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n" 339 if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n"
356 << indent << scope_tab << "public System.Byte " << field_name << ";\n") 340 << indent << scope_tab << "private System.Byte " << field_name << ";\n")
357 .generate(sink, nullptr, context)) 341 .generate(sink, nullptr, context))
358 return false; 342 return false;
359 } 343 }
360 else if (!as_generator(indent << scope_tab << eolian_mono::marshall_annotation(false) << "\n" 344 else if (!as_generator(indent << scope_tab << eolian_mono::marshall_annotation(false) << "\n"
361 << indent << scope_tab << "public " << eolian_mono::marshall_type(false) << " " << string << ";\n") 345 << indent << scope_tab << "private " << eolian_mono::marshall_type(false) << " " << string << ";\n")
362 .generate(sink, std::make_tuple(field.type, field.type, field_name), context)) 346 .generate(sink, std::make_tuple(field.type, field.type, field_name), context))
363 return false; 347 return false;
364 } 348 }
@@ -369,59 +353,18 @@ struct struct_internal_definition_generator
369 // those 'mini-amd64.c condition fields not met' crashes. 353 // those 'mini-amd64.c condition fields not met' crashes.
370 if (struct_.fields.size() == 0) 354 if (struct_.fields.size() == 0)
371 { 355 {
372 if (!as_generator(indent << scope_tab << "internal IntPtr field;\n").generate(sink, nullptr, context)) 356 if (!as_generator(indent << scope_tab << "/// <summary>Placeholder field</summary>\n"
357 << indent << scope_tab << "private IntPtr field;\n").generate(sink, nullptr, context))
373 return false; 358 return false;
374 } 359 }
375 360
376 auto external_name = binding_struct_name(struct_); 361 if(!as_generator("\n")
377 auto internal_name = binding_struct_internal_name(struct_); 362 .generate(sink, attributes::unused, context))
378
379 // to internal
380 if (!as_generator(
381 indent << scope_tab << "/// <summary>Implicit conversion to the internal/marshalling representation.</summary>\n"
382 << indent << scope_tab << "public static implicit operator " << string << "(" << string << " _external_struct)\n"
383 << indent << scope_tab << "{\n"
384 << indent << scope_tab << scope_tab << "var _internal_struct = new " << string << "();\n"
385 ).generate(sink, std::make_tuple(internal_name, external_name, internal_name), context))
386 return false;
387
388 for (auto const& field : struct_.fields)
389 {
390 if (!to_internal_field_convert.generate(sink, field, context))
391 return false;
392 }
393
394 if (!as_generator(indent << scope_tab << scope_tab << "return _internal_struct;\n"
395 << indent << scope_tab << "}\n\n").generate(sink, nullptr, context))
396 return false;
397
398 // to managed
399 if (!as_generator(
400 indent << scope_tab << "/// <summary>Implicit conversion to the managed representation.</summary>\n"
401 << indent << scope_tab << "public static implicit operator " << string << "(" << string << " _internal_struct)\n"
402 << indent << scope_tab << "{\n"
403 << indent << scope_tab << scope_tab << "var _external_struct = new " << string << "();\n"
404 ).generate(sink, std::make_tuple(external_name, internal_name, external_name), context))
405 return false;
406
407 for (auto const& field : struct_.fields)
408 {
409 if (!to_external_field_convert.generate(sink, field, context))
410 return false;
411 }
412
413 if (!as_generator(indent << scope_tab << scope_tab << "return _external_struct;\n"
414 << indent << scope_tab << "}\n").generate(sink, nullptr, context))
415 return false; 363 return false;
416 364
417 // close internal class
418 if(!as_generator(indent << "}\n"
419 << "#pragma warning restore CS1591\n"
420 ).generate(sink, attributes::unused, context)) return false;
421
422 return true; 365 return true;
423 } 366 }
424} const struct_internal_definition {}; 367} const struct_private_property {};
425 368
426// Managed Struct // 369// Managed Struct //
427 370
@@ -454,34 +397,22 @@ struct struct_definition_generator
454 return false; 397 return false;
455 398
456 if (!as_generator( 399 if (!as_generator(
457 indent << scope_tab << "public static implicit operator " << struct_name << "(\n" 400 indent << scope_tab << "public static implicit operator " << struct_name << "(("
458 << indent << scope_tab << scope_tab << "(\n" 401 << (field_argument_decl % ", ")
459 << ((indent << scope_tab << scope_tab << " " << field_argument_decl) % ",\n") << "\n" 402 << ") tuple)\n"
460 << indent << scope_tab << scope_tab << ") tuple)\n"
461 << indent << scope_tab << "{\n"
462 ).generate(sink, struct_.fields, context)) 403 ).generate(sink, struct_.fields, context))
463 return false; 404 return false;
464 405
465 // object constructor 406 // object constructor
466 if (!as_generator( 407 if (!as_generator(
467 indent << scope_tab << scope_tab << "return new " << struct_name << "{\n" 408 indent << scope_tab << scope_tab << "=> new " << struct_name << "("
468 ).generate(sink, attributes::unused, context)) 409 ).generate(sink, attributes::unused, context))
469 return false; 410 return false;
470 411
471 for (const auto& field: struct_.fields)
472 {
473 auto field_name = name_helpers::to_field_name(field.name);
474
475 if (!as_generator(
476 indent << scope_tab << scope_tab << scope_tab << field_name << " = tuple." << field_name << ",\n"
477 ).generate(sink, attributes::unused, context))
478 return false;
479 }
480
481 if (!as_generator( 412 if (!as_generator(
482 indent << scope_tab << scope_tab << "};\n" 413 (("tuple." << struct_field_name) % ", ")
483 << indent << scope_tab << "}\n" 414 << ");\n\n"
484 ).generate(sink, attributes::unused, context)) 415 ).generate(sink, struct_.fields, context))
485 return false; 416 return false;
486 417
487 return true; 418 return true;
@@ -528,10 +459,11 @@ struct struct_definition_generator
528 // assigments 459 // assigments
529 for (auto const& field : struct_.fields) 460 for (auto const& field : struct_.fields)
530 { 461 {
531 auto field_name = name_helpers::to_field_name(field.name); 462 auto field_name = name_helpers::managed_name(field.name);
463 auto param_name = name_helpers::to_field_name(field.name);
532 464
533 if (!as_generator( 465 if (!as_generator(
534 indent << scope_tab << scope_tab << field_name << " = this." << field_name << ";\n" 466 indent << scope_tab << scope_tab << param_name << " = this." << field_name << ";\n"
535 ).generate(sink, attributes::unused, context)) 467 ).generate(sink, attributes::unused, context))
536 return false; 468 return false;
537 } 469 }
@@ -561,6 +493,9 @@ struct struct_definition_generator
561 .generate(sink, attributes::unused, context)) 493 .generate(sink, attributes::unused, context))
562 return false; 494 return false;
563 495
496 if (!struct_private_property.generate(sink, struct_, change_indentation(indent, context)))
497 return false;
498
564 // iterate struct fields 499 // iterate struct fields
565 for (auto const& field : struct_.fields) 500 for (auto const& field : struct_.fields)
566 { 501 {
@@ -574,23 +509,13 @@ struct struct_definition_generator
574 return false; 509 return false;
575 } 510 }
576 511
577 if (!as_generator(indent << scope_tab << "public " << type << " " << name_helpers::to_field_name(field.name) << ";\n").generate(sink, field.type, context)) 512 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))
578 return false; 513 return false;
579 } 514 }
580 515
581 auto struct_name = binding_struct_name(struct_); 516 auto struct_name = binding_struct_name(struct_);
582 517
583 // Check whether this is an extern struct without declared fields in .eo file and generate a 518 if (struct_.fields.size() != 0)
584 // placeholder field if positive.
585 // Mono's JIT is picky when generating function pointer for delegates with empty structs, leading to
586 // those 'mini-amd64.c condition fields not met' crashes.
587 if (struct_.fields.size() == 0)
588 {
589 if (!as_generator(indent << scope_tab << "/// <summary>Placeholder field</summary>\n"
590 << indent << scope_tab << "public IntPtr field;\n").generate(sink, nullptr, context))
591 return false;
592 }
593 else
594 { 519 {
595 // Constructor with default parameters for easy struct initialization 520 // Constructor with default parameters for easy struct initialization
596 if(!as_generator( 521 if(!as_generator(
@@ -608,9 +533,9 @@ struct struct_definition_generator
608 << *(indent << scope_tab << field_argument_docs << "\n") 533 << *(indent << scope_tab << field_argument_docs << "\n")
609 << indent << scope_tab << "public " << string << "(\n" 534 << indent << scope_tab << "public " << string << "(\n"
610 << ((indent << scope_tab << scope_tab << field_argument_default) % ",\n") 535 << ((indent << scope_tab << scope_tab << field_argument_default) % ",\n")
611 << indent << scope_tab << ")\n" 536 << ")\n"
612 << indent << scope_tab << "{\n" 537 << indent << scope_tab << "{\n"
613 << *(indent << scope_tab << scope_tab << field_argument_assignment << ";\n") 538 << *(indent << scope_tab << scope_tab << field_argument_assignment)
614 << indent << scope_tab << "}\n\n") 539 << indent << scope_tab << "}\n\n")
615 .generate(sink, std::make_tuple(struct_.fields, struct_name, struct_.fields, struct_.fields), context)) 540 .generate(sink, std::make_tuple(struct_.fields, struct_name, struct_.fields, struct_.fields), context))
616 return false; 541 return false;
@@ -638,7 +563,14 @@ struct struct_definition_generator
638 ).generate(sink, attributes::unused, context)) 563 ).generate(sink, attributes::unused, context))
639 return false; 564 return false;
640 565
641 if (struct_.fields.size() != 0 ) 566 if (struct_.fields.size() == 1 )
567 {
568 if (!as_generator(
569 indent << scope_tab << scope_tab << "return " << name_helpers::managed_name(struct_.fields[0].name) << ".GetHashCode();\n"
570 ).generate(sink, attributes::unused, context))
571 return false;
572 }
573 else if (struct_.fields.size() != 0 )
642 { 574 {
643 // int hash = 17; 575 // int hash = 17;
644 // hash = 23 * fieldA.GetHashCode(); 576 // hash = 23 * fieldA.GetHashCode();
@@ -647,7 +579,7 @@ struct struct_definition_generator
647 // return hash 579 // return hash
648 if (!as_generator( 580 if (!as_generator(
649 indent << scope_tab << scope_tab << "int hash = 17;\n" 581 indent << scope_tab << scope_tab << "int hash = 17;\n"
650 << *(grammar::attribute_reorder<-1, -1>(indent << scope_tab << scope_tab << "hash = hash * 23 + " << name_helpers::struct_field_name << ".GetHashCode(" << culture_info << ");\n")) 582 << *(grammar::attribute_reorder<-1, -1>(indent << scope_tab << scope_tab << "hash = hash * 23 + " << name_helpers::struct_property_name << ".GetHashCode(" << culture_info << ");\n"))
651 << indent << scope_tab << scope_tab << "return hash;\n" 583 << indent << scope_tab << scope_tab << "return hash;\n"
652 ).generate(sink, struct_.fields, context)) 584 ).generate(sink, struct_.fields, context))
653 return false; 585 return false;
@@ -656,7 +588,7 @@ struct struct_definition_generator
656 { 588 {
657 // Just compare the place holder pointers 589 // Just compare the place holder pointers
658 if (!as_generator( 590 if (!as_generator(
659 "return field.GetHashCode();\n" 591 indent << scope_tab << scope_tab << "return field.GetHashCode();\n"
660 ).generate(sink, attributes::unused, context)) 592 ).generate(sink, attributes::unused, context))
661 return false; 593 return false;
662 } 594 }
@@ -680,7 +612,7 @@ struct struct_definition_generator
680 if (struct_.fields.size() != 0 ) 612 if (struct_.fields.size() != 0 )
681 { 613 {
682 if (!as_generator( 614 if (!as_generator(
683 grammar::attribute_reorder<-1, -1>((name_helpers::struct_field_name << " == other." << name_helpers::struct_field_name)) % " && " 615 grammar::attribute_reorder<-1, -1>((name_helpers::struct_property_name << " == other." << name_helpers::struct_property_name)) % " && "
684 ).generate(sink, struct_.fields, context)) 616 ).generate(sink, struct_.fields, context))
685 return false; 617 return false;
686 } 618 }
@@ -695,7 +627,7 @@ struct struct_definition_generator
695 627
696 628
697 if (!as_generator( 629 if (!as_generator(
698 indent << scope_tab << scope_tab << ";\n" 630 ";\n"
699 << indent << scope_tab << "}\n" 631 << indent << scope_tab << "}\n"
700 ).generate(sink, attributes::unused, context)) 632 ).generate(sink, attributes::unused, context))
701 return false; 633 return false;
@@ -745,8 +677,7 @@ struct struct_definition_generator
745 << indent << scope_tab << "/// <param name=\"ptr\">Native pointer to be converted.</param>\n" 677 << indent << scope_tab << "/// <param name=\"ptr\">Native pointer to be converted.</param>\n"
746 << indent << scope_tab << "public static implicit operator " << struct_name << "(IntPtr ptr)\n" 678 << indent << scope_tab << "public static implicit operator " << struct_name << "(IntPtr ptr)\n"
747 << indent << scope_tab << "{\n" 679 << indent << scope_tab << "{\n"
748 << indent << scope_tab << scope_tab << "var tmp = (" << struct_name << ".NativeStruct)Marshal.PtrToStructure(ptr, typeof(" << struct_name << ".NativeStruct));\n" 680 << indent << scope_tab << scope_tab << "return (" << struct_name << ")Marshal.PtrToStructure(ptr, typeof(" << struct_name << "));\n"
749 << indent << scope_tab << scope_tab << "return tmp;\n"
750 << indent << scope_tab << "}\n\n" 681 << indent << scope_tab << "}\n\n"
751 ).generate(sink, attributes::unused, context)) 682 ).generate(sink, attributes::unused, context))
752 return false; 683 return false;
@@ -771,9 +702,6 @@ struct struct_definition_generator
771 ).generate(sink, attributes::unused, context)) 702 ).generate(sink, attributes::unused, context))
772 return false; 703 return false;
773 704
774 if (!struct_internal_definition.generate(sink, struct_, change_indentation(indent.inc(), context)))
775 return false;
776
777 if(!as_generator(indent << "}\n\n").generate(sink, attributes::unused, context)) return false; 705 if(!as_generator(indent << "}\n\n").generate(sink, attributes::unused, context)) return false;
778 706
779 return true; 707 return true;
@@ -809,9 +737,9 @@ template <>
809struct is_generator< ::eolian_mono::struct_definition_generator> : std::true_type {}; 737struct is_generator< ::eolian_mono::struct_definition_generator> : std::true_type {};
810 738
811template <> 739template <>
812struct is_eager_generator< ::eolian_mono::struct_internal_definition_generator> : std::true_type {}; 740struct is_eager_generator< ::eolian_mono::struct_private_property_generator> : std::true_type {};
813template <> 741template <>
814struct is_generator< ::eolian_mono::struct_internal_definition_generator> : std::true_type {}; 742struct is_generator< ::eolian_mono::struct_private_property_generator> : std::true_type {};
815 743
816template <> 744template <>
817struct is_eager_generator< ::eolian_mono::to_internal_field_convert_generator> : std::true_type {}; 745struct is_eager_generator< ::eolian_mono::to_internal_field_convert_generator> : std::true_type {};
@@ -833,7 +761,7 @@ template <>
833struct attributes_needed< ::eolian_mono::struct_definition_generator> : std::integral_constant<int, 1> {}; 761struct attributes_needed< ::eolian_mono::struct_definition_generator> : std::integral_constant<int, 1> {};
834 762
835template <> 763template <>
836struct attributes_needed< ::eolian_mono::struct_internal_definition_generator> : std::integral_constant<int, 1> {}; 764struct attributes_needed< ::eolian_mono::struct_private_property_generator> : std::integral_constant<int, 1> {};
837 765
838template <> 766template <>
839struct attributes_needed< ::eolian_mono::to_internal_field_convert_generator> : std::integral_constant<int, 1> {}; 767struct attributes_needed< ::eolian_mono::to_internal_field_convert_generator> : std::integral_constant<int, 1> {};
diff --git a/src/bin/eolian_mono/eolian/mono/struct_fields.hh b/src/bin/eolian_mono/eolian/mono/struct_fields.hh
index 76e0f64138..a9f400bbc5 100644
--- a/src/bin/eolian_mono/eolian/mono/struct_fields.hh
+++ b/src/bin/eolian_mono/eolian/mono/struct_fields.hh
@@ -69,11 +69,121 @@ struct field_argument_assignment_generator
69 template<typename OutputIterator, typename Context> 69 template<typename OutputIterator, typename Context>
70 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const 70 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const
71 { 71 {
72 auto field_name = name_helpers::to_field_name(field.name); 72 auto field_name = to_field_name(field.name);
73 if (!as_generator("this." << field_name << " = " << field_name) 73 // FIXME Replace need_struct_conversion(regular) with need_struct_conversion(type)
74 .generate(sink, attributes::unused, context)) 74 auto regular = efl::eina::get<attributes::regular_type_def>(&field.type.original_type);
75 return false; 75 auto klass = efl::eina::get<attributes::klass_name>(&field.type.original_type);
76 return true; 76 auto complex = efl::eina::get<attributes::complex_type_def>(&field.type.original_type);
77
78 if (klass)
79 {
80 if (!as_generator(
81 "this." << string << " = " << string << "?.NativeHandle ?? System.IntPtr.Zero;\n")
82 .generate(sink, std::make_tuple(field_name, field_name), context))
83 return false;
84 }
85 else if ((complex && (complex->outer.base_type == "array")))
86 {
87 if (!as_generator(
88 "this." << string << " = Efl.Eo.Globals.IListToNativeArray(" << string << ", " << (field.type.has_own ? "true" : "false") << ");\n")
89 .generate(sink, std::make_tuple(field_name, field_name), context))
90 return false;
91 }
92 else if ((complex && (complex->outer.base_type == "list")))
93 {
94 if (!as_generator(
95 "this." << string << " = Efl.Eo.Globals.IListToNativeList(" << string << ", " << (field.type.has_own ? "true" : "false") << ");\n")
96 .generate(sink, std::make_tuple(field_name, field_name), context))
97 return false;
98 }
99 else if ((complex && (complex->outer.base_type == "iterator")))
100 {
101 if (!as_generator(
102 "this." << string << " = Efl.Eo.Globals.IEnumerableToIterator(" << string << ", " << (field.type.has_own ? "true" : "false") << ");\n")
103 .generate(sink, std::make_tuple(field_name, field_name), context))
104 return false;
105 }
106 else if ((complex && (complex->outer.base_type == "hash"))
107 || field.type.c_type == "Eina_Binbuf *" || field.type.c_type == "const Eina_Binbuf *")
108 {
109 // Always assumes pointer
110 if (!as_generator(
111 "this." << string << " = " << string << ".Handle;\n")
112 .generate(sink, std::make_tuple(field_name, field_name), context))
113 return false;
114 }
115 else if (field.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular))
116 {
117 if (!as_generator(
118 "this." << string << " = Eina.PrimitiveConversion.ManagedToPointerAlloc(" << string << ");\n")
119 .generate(sink, std::make_tuple(field_name, field_name), context))
120 return false;
121 }
122 else if (helpers::need_struct_conversion(regular))
123 {
124 if (!as_generator(
125 "this." << string << " = " << string << ";\n")
126 .generate(sink, std::make_tuple(field_name, field_name), context))
127 return false;
128 }
129 else if (regular && (regular->base_type == "string" || regular->base_type == "mstring"))
130 {
131 if (!as_generator(
132 "this." << string << " = Eina.MemoryNative.StrDup(" << string << ");\n")
133 .generate(sink, std::make_tuple(field_name, field_name), context))
134 return false;
135 }
136 else if (regular && regular->base_type == "stringshare")
137 {
138 if (!as_generator(
139 "this." << string << " = Eina.MemoryNative.AddStringshare(" << string << ");\n")
140 .generate(sink, std::make_tuple(field_name, field_name), context))
141 return false;
142 }
143 else if (field.type.c_type == "Eina_Slice" || field.type.c_type == "const Eina_Slice"
144 || field.type.c_type == "Eina_Rw_Slice" || field.type.c_type == "const Eina_Rw_Slice")
145 {
146 if (!as_generator(
147 "this." << string << " = " << string << ";\n")
148 .generate(sink, std::make_tuple(field_name, field_name), context))
149 return false;
150 }
151 else if (field.type.c_type == "Eina_Value" || field.type.c_type == "const Eina_Value")
152 {
153 if (!as_generator(
154 "this." << string << " = " << string << ".GetNative();\n"
155 ).generate(sink, std::make_tuple(field_name, field_name), context))
156 return false;
157 }
158 else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *")
159 {
160 if (!as_generator(
161 "this." << string << " = " << string << "?.NativeHandle ?? System.IntPtr.Zero;\n"
162 ).generate(sink, std::make_tuple(field_name, field_name), context))
163 return false;
164 }
165 else if (!field.type.is_ptr && regular && regular->base_type == "bool")
166 {
167 if (!as_generator(
168 "this." << string << " = " << string << " ? (byte)1 : (byte)0;\n")
169 .generate(sink, std::make_tuple(field_name, field_name), context))
170 return false;
171 }
172 else if (!field.type.is_ptr && regular && regular->base_type == "char")
173 {
174 if (!as_generator(
175 "this." << string << " = (byte)" << string << ";\n")
176 .generate(sink, std::make_tuple(field_name, field_name), context))
177 return false;
178 }
179 else // primitives and enums
180 {
181 if (!as_generator(
182 "this." << string << " = " << string << ";\n")
183 .generate(sink, std::make_tuple(field_name, field_name), context))
184 return false;
185 }
186 return true;
77 } 187 }
78} const field_argument_assignment {}; 188} const field_argument_assignment {};
79 189
diff --git a/src/bin/eolian_mono/eolian/mono/utils.hh b/src/bin/eolian_mono/eolian/mono/utils.hh
index d942903aba..7905790b4c 100644
--- a/src/bin/eolian_mono/eolian/mono/utils.hh
+++ b/src/bin/eolian_mono/eolian/mono/utils.hh
@@ -90,6 +90,28 @@ namespace eolian_mono { namespace utils {
90 return ret; 90 return ret;
91 } 91 }
92 92
93 std::string to_camel_case(const std::vector<std::string> &names, std::string const& delim="")
94 {
95 std::vector<std::string> outv(names.size());
96 std::stringstream osstream;
97
98 std::transform(names.begin(), names.end(), outv.begin(),
99 [](std::string name) {
100 name[0] = std::toupper(name[0]);
101 return name;
102 });
103
104 std::copy(outv.begin(), outv.end(), std::ostream_iterator<std::string>(osstream, delim.c_str()));
105
106 std::string ret = osstream.str();
107
108 if (delim != "")
109 ret.pop_back(); // We could implement an infix_iterator but this pop is enough for now.
110
111 ret[0] = std::tolower(ret[0]);
112 return ret;
113 }
114
93 inline std::string remove_all(std::string name, char target) 115 inline std::string remove_all(std::string name, char target)
94 { 116 {
95 name.erase(std::remove(name.begin(), name.end(), target), name.end()); 117 name.erase(std::remove(name.begin(), name.end(), target), name.end());
diff --git a/src/bindings/mono/eo_mono/EoWrapper.cs b/src/bindings/mono/eo_mono/EoWrapper.cs
index 99e60b1d2b..db618232c4 100644
--- a/src/bindings/mono/eo_mono/EoWrapper.cs
+++ b/src/bindings/mono/eo_mono/EoWrapper.cs
@@ -328,7 +328,7 @@ public abstract class EoWrapper : IWrapper, IDisposable
328 328
329 internal Efl.EventCb GetInternalEventCallback<T>(EventHandler<T> handler, Func<IntPtr, T> createArgsInstance) where T:EventArgs 329 internal Efl.EventCb GetInternalEventCallback<T>(EventHandler<T> handler, Func<IntPtr, T> createArgsInstance) where T:EventArgs
330 { 330 {
331 return (IntPtr data, ref Efl.Event.NativeStruct evt) => 331 return (IntPtr data, ref Efl.Event evt) =>
332 { 332 {
333 var obj = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data).Target; 333 var obj = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data).Target;
334 if (obj != null) 334 if (obj != null)
@@ -348,7 +348,7 @@ public abstract class EoWrapper : IWrapper, IDisposable
348 348
349 internal Efl.EventCb GetInternalEventCallback(EventHandler handler) 349 internal Efl.EventCb GetInternalEventCallback(EventHandler handler)
350 { 350 {
351 return (IntPtr data, ref Efl.Event.NativeStruct evt) => 351 return (IntPtr data, ref Efl.Event evt) =>
352 { 352 {
353 var obj = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data).Target; 353 var obj = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data).Target;
354 if (obj != null) 354 if (obj != null)
@@ -383,13 +383,13 @@ public abstract class EoWrapper : IWrapper, IDisposable
383 } 383 }
384 } 384 }
385 385
386 private static void OwnershipUniqueCallback(IntPtr data, ref Efl.Event.NativeStruct evt) 386 private static void OwnershipUniqueCallback(IntPtr data, ref Efl.Event evt)
387 { 387 {
388 var ws = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data); 388 var ws = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data);
389 ws.MakeUnique(); 389 ws.MakeUnique();
390 } 390 }
391 391
392 private static void OwnershipSharedCallback(IntPtr data, ref Efl.Event.NativeStruct evt) 392 private static void OwnershipSharedCallback(IntPtr data, ref Efl.Event evt)
393 { 393 {
394 var ws = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data); 394 var ws = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data);
395 ws.MakeShared(); 395 ws.MakeShared();
diff --git a/src/bindings/mono/eo_mono/workaround.cs b/src/bindings/mono/eo_mono/workaround.cs
index 0afe95807b..3e6829feef 100644
--- a/src/bindings/mono/eo_mono/workaround.cs
+++ b/src/bindings/mono/eo_mono/workaround.cs
@@ -173,17 +173,24 @@ internal struct EventDescription
173[Efl.Eo.BindingEntity] 173[Efl.Eo.BindingEntity]
174internal struct Event 174internal struct Event
175{ 175{
176 /// <summary>Internal wrapper for field Object</summary>
177 private System.IntPtr obj;
178 /// <summary>Internal wrapper for field Desc</summary>
179 private System.IntPtr desc;
180 /// <summary>Internal wrapper for field Info</summary>
181 private System.IntPtr info;
182
176 /// <summary> 183 /// <summary>
177 /// The object the callback was called on. 184 /// The object the callback was called on.
178 /// <para>Since EFL 1.22.</para> 185 /// <para>Since EFL 1.22.</para>
179 /// </summary> 186 /// </summary>
180 public Efl.Object Object; 187 public Efl.Object Object { get => (Efl.Object) Efl.Eo.Globals.CreateWrapperFor(obj); }
181 188
182 /// <summary> 189 /// <summary>
183 /// The event description. 190 /// The event description.
184 /// <para>Since EFL 1.22.</para> 191 /// <para>Since EFL 1.22.</para>
185 /// </summary> 192 /// </summary>
186 public Efl.EventDescription Desc; 193 public Efl.EventDescription Desc { get => Eina.PrimitiveConversion.PointerToManaged<Efl.EventDescription>(desc); }
187 194
188 /// <summary> 195 /// <summary>
189 /// Extra event information passed by the event caller. 196 /// Extra event information passed by the event caller.
@@ -192,7 +199,7 @@ internal struct Event
192 /// 2) Structs, built-in types and containers are passed as const pointers, with one level of indirection. 199 /// 2) Structs, built-in types and containers are passed as const pointers, with one level of indirection.
193 /// <para>Since EFL 1.22.</para> 200 /// <para>Since EFL 1.22.</para>
194 /// </summary> 201 /// </summary>
195 public System.IntPtr Info; 202 public System.IntPtr Info { get => info; }
196 203
197 /// <summary>Constructor for Event.</summary> 204 /// <summary>Constructor for Event.</summary>
198 public Event( 205 public Event(
@@ -200,59 +207,21 @@ internal struct Event
200 Efl.EventDescription desc = default(Efl.EventDescription), 207 Efl.EventDescription desc = default(Efl.EventDescription),
201 System.IntPtr info = default(System.IntPtr)) 208 System.IntPtr info = default(System.IntPtr))
202 { 209 {
203 this.Object = obj; 210 this.obj = obj?.NativeHandle ?? System.IntPtr.Zero;
204 this.Desc = desc; 211 this.desc = Eina.PrimitiveConversion.ManagedToPointerAlloc(desc);
205 this.Info = info; 212 this.info = info;
206 } 213 }
207 214
208 /// <summary>Implicit conversion to the managed representation from a native pointer.</summary> 215 /// <summary>Implicit conversion to the managed representation from a native pointer.</summary>
209 /// <param name="ptr">Native pointer to be converted.</param> 216 /// <param name="ptr">Native pointer to be converted.</param>
210 public static implicit operator Event(IntPtr ptr) 217 public static implicit operator Event(IntPtr ptr)
211 { 218 {
212 var tmp = (Event.NativeStruct) Marshal.PtrToStructure(ptr, typeof(Event.NativeStruct)); 219 var tmp = (Event) Marshal.PtrToStructure(ptr, typeof(Event));
213 return tmp; 220 return tmp;
214 } 221 }
215
216 /// <summary>Internal wrapper for struct Event.</summary>
217 [StructLayout(LayoutKind.Sequential)]
218 public struct NativeStruct
219 {
220 /// <summary>Internal wrapper for field Object</summary>
221 public System.IntPtr Object;
222
223 /// <summary>Internal wrapper for field Desc</summary>
224 public System.IntPtr Desc;
225
226 /// <summary>Internal wrapper for field Info</summary>
227 public System.IntPtr Info;
228
229 /// <summary>Implicit conversion to the internal/marshalling representation.</summary>
230 /// <param name="externalStruct">Managed struct to be converted.</param>
231 /// <returns>Native representation of the managed struct.</returns>
232 public static implicit operator Event.NativeStruct(Event externalStruct)
233 {
234 var internalStruct = new Event.NativeStruct();
235 internalStruct.Object = externalStruct.Object?.NativeHandle ?? System.IntPtr.Zero;
236 internalStruct.Desc = Eina.PrimitiveConversion.ManagedToPointerAlloc(externalStruct.Desc);
237 internalStruct.Info = externalStruct.Info;
238 return internalStruct;
239 }
240
241 /// <summary>Implicit conversion to the managed representation.</summary>
242 /// <param name="internalStruct">Native struct to be converted.</param>
243 /// <returns>Managed representation of the native struct.</returns>
244 public static implicit operator Event(Event.NativeStruct internalStruct)
245 {
246 var externalStruct = new Event();
247 externalStruct.Object = (Efl.Object) Efl.Eo.Globals.CreateWrapperFor(internalStruct.Object);
248 externalStruct.Desc = Eina.PrimitiveConversion.PointerToManaged<Efl.EventDescription>(internalStruct.Desc);
249 externalStruct.Info = internalStruct.Info;
250 return externalStruct;
251 }
252 }
253} 222}
254 223
255internal delegate void EventCb(System.IntPtr data, ref Event.NativeStruct evt); 224internal delegate void EventCb(System.IntPtr data, ref Event evt);
256internal delegate void FreeWrapperSupervisorCb(System.IntPtr obj); 225internal delegate void FreeWrapperSupervisorCb(System.IntPtr obj);
257 226
258namespace Access 227namespace Access
diff --git a/src/tests/efl_mono/Events.cs b/src/tests/efl_mono/Events.cs
index c10c37911e..2abcc98b63 100644
--- a/src/tests/efl_mono/Events.cs
+++ b/src/tests/efl_mono/Events.cs
@@ -196,8 +196,7 @@ class TestEoEvents
196 received_struct = e.arg; 196 received_struct = e.arg;
197 }; 197 };
198 198
199 Dummy.StructSimple sent_struct = default(Dummy.StructSimple); 199 Dummy.StructSimple sent_struct = new Dummy.StructSimple(fstring: "Struct Event");
200 sent_struct.Fstring = "Struct Event";
201 200
202 obj.EmitEventWithStruct(sent_struct); 201 obj.EmitEventWithStruct(sent_struct);
203 202
diff --git a/src/tests/efl_mono/StructHelpers.cs b/src/tests/efl_mono/StructHelpers.cs
index 5e6dc506a7..495638458a 100644
--- a/src/tests/efl_mono/StructHelpers.cs
+++ b/src/tests/efl_mono/StructHelpers.cs
@@ -30,40 +30,38 @@ internal class StructHelpers
30 30
31 internal static Dummy.StructSimple structSimpleWithValues() 31 internal static Dummy.StructSimple structSimpleWithValues()
32 { 32 {
33 var simple = new Dummy.StructSimple(); 33 return new Dummy.StructSimple(
34 34 fbyte: (sbyte)-126,
35 simple.Fbyte = (sbyte)-126; 35 fubyte: (byte) 254u,
36 simple.Fubyte = (byte) 254u; 36 fchar: '~',
37 simple.Fchar = '~'; 37 fshort: (short) -32766,
38 simple.Fshort = (short) -32766; 38 fushort: (ushort) 65534u,
39 simple.Fushort = (ushort) 65534u; 39 fint: -32766,
40 simple.Fint = -32766; 40 fuint: 65534u,
41 simple.Fuint = 65534u; 41 flong: -2147483646,
42 simple.Flong = -2147483646; 42 fulong: 4294967294u,
43 simple.Fulong = 4294967294u; 43 fllong: -9223372036854775806,
44 simple.Fllong = -9223372036854775806; 44 fullong: 18446744073709551614u,
45 simple.Fullong = 18446744073709551614u; 45 fint8: (sbyte) -126,
46 simple.Fint8 = (sbyte) -126; 46 fuint8: (byte) 254u,
47 simple.Fuint8 = (byte) 254u; 47 fint16: (short) -32766,
48 simple.Fint16 = (short) -32766; 48 fuint16: (ushort) 65534u,
49 simple.Fuint16 = (ushort) 65534u; 49 fint32: -2147483646,
50 simple.Fint32 = -2147483646; 50 fuint32: 4294967294u,
51 simple.Fuint32 = 4294967294u; 51 fint64: -9223372036854775806,
52 simple.Fint64 = -9223372036854775806; 52 fuint64: 18446744073709551614u,
53 simple.Fuint64 = 18446744073709551614u; 53 fssize: -2147483646,
54 simple.Fssize = -2147483646; 54 fsize: 4294967294u,
55 simple.Fsize = 4294967294u; 55 fintptr: (IntPtr) 0xFE,
56 simple.Fintptr = (IntPtr) 0xFE; 56 fptrdiff: -2147483646,
57 simple.Fptrdiff = -2147483646; 57 ffloat: -16777216.0f,
58 simple.Ffloat = -16777216.0f; 58 fdouble: -9007199254740992.0,
59 simple.Fdouble = -9007199254740992.0; 59 fbool: true,
60 simple.Fbool = true; 60 fenum: Dummy.SampleEnum.V2,
61 simple.Fenum = Dummy.SampleEnum.V2; 61 fstring: "test/string",
62 simple.Fstring = "test/string"; 62 fmstring: "test/mstring",
63 simple.Fmstring = "test/mstring"; 63 fstringshare: "test/stringshare"
64 simple.Fstringshare = "test/stringshare"; 64 );
65
66 return simple;
67 } 65 }
68 66
69 internal static void checkStructSimple(Dummy.StructSimple simple) 67 internal static void checkStructSimple(Dummy.StructSimple simple)
@@ -137,42 +135,41 @@ internal class StructHelpers
137#if EFL_BETA 135#if EFL_BETA
138 internal static Dummy.StructComplex structComplexWithValues() 136 internal static Dummy.StructComplex structComplexWithValues()
139 { 137 {
140 var complex = new Dummy.StructComplex(); 138 var Farray = new Eina.Array<string>();
139 Farray.Add("0x0");
140 Farray.Add("0x2A");
141 Farray.Add("0x42");
141 142
142 complex.Farray = new Eina.Array<string>(); 143 var Flist = new Eina.List<string>();
143 complex.Farray.Add("0x0"); 144 Flist.Add("0x0");
144 complex.Farray.Add("0x2A"); 145 Flist.Add("0x2A");
145 complex.Farray.Add("0x42"); 146 Flist.Add("0x42");
146 147
147 complex.Flist = new Eina.List<string>(); 148 var Fhash = new Eina.Hash<string, string>();
148 complex.Flist.Add("0x0"); 149 Fhash["aa"] = "aaa";
149 complex.Flist.Add("0x2A"); 150 Fhash["bb"] = "bbb";
150 complex.Flist.Add("0x42"); 151 Fhash["cc"] = "ccc";
151 152
152 complex.Fhash = new Eina.Hash<string, string>(); 153 var Fiterator = ((Eina.Array<string>)Farray).GetIterator();
153 complex.Fhash["aa"] = "aaa";
154 complex.Fhash["bb"] = "bbb";
155 complex.Fhash["cc"] = "ccc";
156 154
157 complex.Fiterator = ((Eina.Array<string>)complex.Farray).GetIterator(); 155 var Fany_value = new Eina.Value(Eina.ValueType.Double);
156 Fany_value.Set(-9007199254740992.0);
158 157
159 complex.Fany_value = new Eina.Value(Eina.ValueType.Double); 158 var Fany_value_ref = new Eina.Value(Eina.ValueType.String);
160 complex.Fany_value.Set(-9007199254740992.0); 159 Fany_value_ref.Set("abc");
161 160
162 complex.Fany_value_ref = new Eina.Value(Eina.ValueType.String); 161 var Fbinbuf = new Eina.Binbuf();
163 complex.Fany_value_ref.Set("abc"); 162 Fbinbuf.Append(126);
164 163
165 complex.Fbinbuf = new Eina.Binbuf(); 164 var Fslice = new Eina.Slice(Eina.MemoryNative.Alloc(1), (UIntPtr)1);
166 complex.Fbinbuf.Append(126); 165 Marshal.WriteByte(Fslice.Mem, 125);
167 166
168 complex.Fslice.Length = 1; 167 var Fobj = new Dummy.Numberwrapper();
169 complex.Fslice.Mem = Eina.MemoryNative.Alloc(1); 168 Fobj.SetNumber(42);
170 Marshal.WriteByte(complex.Fslice.Mem, 125);
171 169
172 complex.Fobj = new Dummy.Numberwrapper(); 170 return new Dummy.StructComplex(farray: Farray, flist: Flist, fhash: Fhash,
173 complex.Fobj.SetNumber(42); 171 fiterator: Fiterator, fanyValue:Fany_value, fanyValueRef: Fany_value_ref,
174 172 fbinbuf: Fbinbuf, fslice:Fslice, fobj: Fobj);
175 return complex;
176 } 173 }
177 174
178 internal static void checkStructComplex(Dummy.StructComplex complex) 175 internal static void checkStructComplex(Dummy.StructComplex complex)
@@ -194,11 +191,11 @@ internal class StructHelpers
194 Test.AssertEquals(idx, base_seq_str.Length); 191 Test.AssertEquals(idx, base_seq_str.Length);
195 192
196 double double_val = 0; 193 double double_val = 0;
197 Test.Assert(complex.Fany_value.Get(out double_val)); 194 Test.Assert(complex.FanyValue.Get(out double_val));
198 Test.Assert(double_val == -9007199254740992.0); 195 Test.Assert(double_val == -9007199254740992.0);
199 196
200 string str_val = null; 197 string str_val = null;
201 Test.Assert(complex.Fany_value_ref.Get(out str_val)); 198 Test.Assert(complex.FanyValueRef.Get(out str_val));
202 Test.Assert(str_val == "abc"); 199 Test.Assert(str_val == "abc");
203 200
204 Test.Assert(complex.Fbinbuf.Length == 1); 201 Test.Assert(complex.Fbinbuf.Length == 1);
@@ -218,8 +215,8 @@ internal class StructHelpers
218 Test.Assert(complex.Flist == null); 215 Test.Assert(complex.Flist == null);
219 Test.Assert(complex.Fhash == null); 216 Test.Assert(complex.Fhash == null);
220 Test.Assert(complex.Fiterator == null); 217 Test.Assert(complex.Fiterator == null);
221 Test.Assert(complex.Fany_value == null); 218 Test.Assert(complex.FanyValue == null);
222 Test.Assert(complex.Fany_value_ref == null); 219 Test.Assert(complex.FanyValueRef == null);
223 Test.Assert(complex.Fbinbuf == null); 220 Test.Assert(complex.Fbinbuf == null);
224 221
225 Test.Assert(complex.Fslice.Length == 0); 222 Test.Assert(complex.Fslice.Length == 0);
diff --git a/src/tests/efl_mono/Structs.cs b/src/tests/efl_mono/Structs.cs
index d546298908..e110f2f15a 100644
--- a/src/tests/efl_mono/Structs.cs
+++ b/src/tests/efl_mono/Structs.cs
@@ -180,8 +180,7 @@ internal class TestStructs
180 180
181 public override bool StructSimpleOut(out Dummy.StructSimple simple) { 181 public override bool StructSimpleOut(out Dummy.StructSimple simple) {
182 called = true; 182 called = true;
183 simple = new Dummy.StructSimple(); 183 simple = new Dummy.StructSimple(fstring: "Virtual Struct Out");
184 simple.Fstring = "Virtual Struct Out";
185 return true; 184 return true;
186 } 185 }
187 186
@@ -206,8 +205,7 @@ internal class TestStructs
206 public override Dummy.StructSimple StructSimpleReturn() 205 public override Dummy.StructSimple StructSimpleReturn()
207 { 206 {
208 called = true; 207 called = true;
209 var simple = new Dummy.StructSimple(); 208 var simple = new Dummy.StructSimple(fstring: "Virtual Struct Return");
210 simple.Fstring = "Virtual Struct Return";
211 return simple; 209 return simple;
212 } 210 }
213 211
@@ -234,7 +232,6 @@ internal class TestStructs
234 { 232 {
235 StructReturner t = new StructReturner(); 233 StructReturner t = new StructReturner();
236 var simple = structSimpleWithValues(); 234 var simple = structSimpleWithValues();
237 simple.Fstring = "Virtual Struct In";
238 235
239 t.CallStructSimpleIn(simple); 236 t.CallStructSimpleIn(simple);
240 Test.Assert(t.called); 237 Test.Assert(t.called);
@@ -379,13 +376,13 @@ internal class TestStructs
379 376
380internal class TestStructEquality 377internal class TestStructEquality
381{ 378{
382 static Dummy.StructSimple a = new Dummy.StructSimple(1, 2, (char)3, 4, Fstring: "", Fmstring: "", Fstringshare: ""); 379 static Dummy.StructSimple a = new Dummy.StructSimple(1, 2, (char)3, 4, fstring: "", fmstring: "", fstringshare: "");
383 static Dummy.StructSimple b = new Dummy.StructSimple(1, 2, (char)3, 4, Fstring: "", Fmstring: "", Fstringshare: ""); 380 static Dummy.StructSimple b = new Dummy.StructSimple(1, 2, (char)3, 4, fstring: "", fmstring: "", fstringshare: "");
384 381
385 static Dummy.StructSimple c = new Dummy.StructSimple(4, 3, (char)2, 1, Fstring: "", Fmstring: "", Fstringshare: ""); 382 static Dummy.StructSimple c = new Dummy.StructSimple(4, 3, (char)2, 1, fstring: "", fmstring: "", fstringshare: "");
386 383
387 // to check if we differ on a single struct field 384 // to check if we differ on a single struct field
388 static Dummy.StructSimple singleDifferentField = new Dummy.StructSimple(1, 2, (char)3, 5, Fstring: "", Fmstring: "", Fstringshare: ""); 385 static Dummy.StructSimple singleDifferentField = new Dummy.StructSimple(1, 2, (char)3, 5, fstring: "", fmstring: "", fstringshare: "");
389 386
390 public static void test_equals() 387 public static void test_equals()
391 { 388 {