summaryrefslogtreecommitdiff
path: root/src/bin/eolian_mono
diff options
context:
space:
mode:
authorLauro Moura <lauromoura@expertisesolutions.com.br>2018-03-15 20:32:39 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2018-03-16 11:12:49 -0300
commit2705ea853108a64edc9264c8e5d4c79e55aea001 (patch)
tree7cbb95f4667ce4fa3d6c44a7b8e0e196a1ca757c /src/bin/eolian_mono
parent7c543d3c860c8c2d6979c55a0460d4ad3c983291 (diff)
csharp: Fix support for ptr(structs)
In general, ptr(struct) parameters behavior depends whether the parameter has the @owned modifier or not. If there is no @owned parameter (meaning no transfer of ownership happens) and it is a "complex" struct, with reference type fields (like strings), the struct is converted to the respective <Struct>Internal struct and passed with "ref" to the DllImport'd function. For @in parameters, after the function it returns, this intermediate struct is converted to the public struct type and assigned to the original parameter, updating it to the external world. When we have ownership transfers, the structure is copied to unmanaged memory and given to the callee. We can't send managed memory directly as the callee may try to free it. On the managed side, the original struct is left to be garbage collected normally.
Diffstat (limited to 'src/bin/eolian_mono')
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_helpers.hh8
-rw-r--r--src/bin/eolian_mono/eolian/mono/helpers.hh24
-rw-r--r--src/bin/eolian_mono/eolian/mono/marshall_type.hh17
-rw-r--r--src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh4
-rw-r--r--src/bin/eolian_mono/eolian/mono/parameter.hh122
-rw-r--r--src/bin/eolian_mono/eolian/mono/struct_definition.hh27
6 files changed, 175 insertions, 27 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/function_helpers.hh b/src/bin/eolian_mono/eolian/mono/function_helpers.hh
index e7af6f9dc0..2b8c912d44 100644
--- a/src/bin/eolian_mono/eolian/mono/function_helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_helpers.hh
@@ -98,9 +98,11 @@ struct native_function_definition_epilogue_generator
98 if (!as_generator( 98 if (!as_generator(
99 scope_tab << scope_tab << "//Assigning out variables\n" 99 scope_tab << scope_tab << "//Assigning out variables\n"
100 << *(scope_tab << scope_tab << native_convert_out_assign(*klass) << "\n") 100 << *(scope_tab << scope_tab << native_convert_out_assign(*klass) << "\n")
101 << scope_tab << scope_tab << "//Placeholder in ptr variables that need to be updated\n"
102 << *(scope_tab << scope_tab << native_convert_in_ptr_assign << "\n")
101 << scope_tab << scope_tab << "//Converting return variable\n" 103 << scope_tab << scope_tab << "//Converting return variable\n"
102 << scope_tab << scope_tab << native_convert_return(*klass) 104 << scope_tab << scope_tab << native_convert_return(*klass)
103 ).generate(sink, std::make_tuple(f.parameters, f.return_type), context)) 105 ).generate(sink, std::make_tuple(f.parameters, f.parameters, f.return_type), context))
104 return false; 106 return false;
105 107
106 return true; 108 return true;
@@ -117,9 +119,11 @@ struct function_definition_epilogue_generator
117 scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n" 119 scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
118 << scope_tab << scope_tab << "//Assigning out variables\n" 120 << scope_tab << scope_tab << "//Assigning out variables\n"
119 << *(scope_tab << scope_tab << convert_out_assign << "\n") 121 << *(scope_tab << scope_tab << convert_out_assign << "\n")
122 << scope_tab << scope_tab << "//Placeholder in ptr variables that need to be updated\n"
123 << *(scope_tab << scope_tab << convert_in_ptr_assign << "\n")
120 << scope_tab << scope_tab << "//Converting return variable\n" 124 << scope_tab << scope_tab << "//Converting return variable\n"
121 << scope_tab << scope_tab << convert_return 125 << scope_tab << scope_tab << convert_return
122 ).generate(sink, std::make_tuple(f.parameters, f.return_type), context)) 126 ).generate(sink, std::make_tuple(f.parameters, f.parameters, f.return_type), context))
123 return false; 127 return false;
124 128
125 return true; 129 return true;
diff --git a/src/bin/eolian_mono/eolian/mono/helpers.hh b/src/bin/eolian_mono/eolian/mono/helpers.hh
index e02fd05b70..d1bebeee14 100644
--- a/src/bin/eolian_mono/eolian/mono/helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/helpers.hh
@@ -53,6 +53,30 @@ inline bool need_struct_conversion(attributes::regular_type_def const* regular)
53 return regular && regular->is_struct() && !is_struct_blacklisted(*regular); 53 return regular && regular->is_struct() && !is_struct_blacklisted(*regular);
54} 54}
55 55
56inline bool need_struct_conversion(attributes::parameter_def const& param, attributes::regular_type_def const* regular)
57{
58 if (param.direction == attributes::parameter_direction::in && param.type.has_own)
59 return false;
60
61 return need_struct_conversion(regular);
62}
63
64inline bool need_struct_conversion_in_return(attributes::type_def const& ret_type, attributes::parameter_direction const& direction)
65{
66 auto regular = efl::eina::get<attributes::regular_type_def>(&ret_type.original_type);
67
68 if (!regular->is_struct())
69 return false;
70
71 if (regular->is_struct() && (direction == attributes::parameter_direction::out || direction == attributes::parameter_direction::unknown))
72 return false;
73
74 if (ret_type.has_own)
75 return false;
76
77 return true;
78}
79
56inline bool need_pointer_conversion(attributes::regular_type_def const* regular) 80inline bool need_pointer_conversion(attributes::regular_type_def const* regular)
57{ 81{
58 if (!regular) 82 if (!regular)
diff --git a/src/bin/eolian_mono/eolian/mono/marshall_type.hh b/src/bin/eolian_mono/eolian/mono/marshall_type.hh
index a946e15ea8..79ce8b6380 100644
--- a/src/bin/eolian_mono/eolian/mono/marshall_type.hh
+++ b/src/bin/eolian_mono/eolian/mono/marshall_type.hh
@@ -16,6 +16,16 @@ struct marshall_annotation_visitor_generate;
16template <typename OutputIterator, typename Context> 16template <typename OutputIterator, typename Context>
17struct marshall_native_annotation_visitor_generate; 17struct marshall_native_annotation_visitor_generate;
18} 18}
19
20/*
21 * Converts a given type/parameter to the type used in the DllImport signatures.
22 *
23 * For example, Eina.Value can be marshaled either as an eina.Value instance through
24 * CustomMarshallers if we have a ptr(Eina.Value) or through the intermediate
25 * eina.Value_Native blittable struct if it is passed by value.
26 *
27 * For details, check marshall_type_impl.h with the actual conversion rules.
28 */
19struct marshall_type_generator 29struct marshall_type_generator
20{ 30{
21 marshall_type_generator(bool is_return = false) 31 marshall_type_generator(bool is_return = false)
@@ -26,6 +36,7 @@ struct marshall_type_generator
26 { 36 {
27 return type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr }); 37 return type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr });
28 } 38 }
39 /* Some types may require a different conversion when they are in @out parameters. */
29 template <typename OutputIterator, typename Context> 40 template <typename OutputIterator, typename Context>
30 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const 41 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
31 { 42 {
@@ -36,6 +47,12 @@ struct marshall_type_generator
36 bool is_return; 47 bool is_return;
37}; 48};
38 49
50/*
51 * Generates the "[MarshalAs(...)]" rules for the given type.
52 *
53 * For example, the CustomMarshallers definitions for String and eina.Values and the
54 * boolean size defintion (Eina_Value is 1 byte, while C# bool has 4 bytes).
55 */
39struct marshall_annotation_generator 56struct marshall_annotation_generator
40{ 57{
41 marshall_annotation_generator(bool is_return = false) 58 marshall_annotation_generator(bool is_return = false)
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 89efc7f3e2..61a53745ca 100644
--- a/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh
+++ b/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh
@@ -149,8 +149,10 @@ struct marshall_type_visitor_generate
149 }} 149 }}
150 }; 150 };
151 151
152 if (!is_ptr && regular.is_struct() && !is_struct_blacklisted(regular)) 152 if (regular.is_struct() && !is_struct_blacklisted(regular) && !(bool)(regular.base_qualifier & qualifier_info::is_own))
153 { 153 {
154 if ((is_out || is_return) && is_ptr)
155 return as_generator(" System.IntPtr").generate(sink, attributes::unused, *context);
154 return as_generator(*(lower_case[string] << ".") << string << "_StructInternal") 156 return as_generator(*(lower_case[string] << ".") << string << "_StructInternal")
155 .generate(sink, std::make_tuple(eolian_mono::escape_namespace(regular.namespaces), regular.base_type), *context); 157 .generate(sink, std::make_tuple(eolian_mono::escape_namespace(regular.namespaces), regular.base_type), *context);
156 } 158 }
diff --git a/src/bin/eolian_mono/eolian/mono/parameter.hh b/src/bin/eolian_mono/eolian/mono/parameter.hh
index d836124fe0..0487ee22b3 100644
--- a/src/bin/eolian_mono/eolian/mono/parameter.hh
+++ b/src/bin/eolian_mono/eolian/mono/parameter.hh
@@ -22,6 +22,8 @@ namespace eolian_mono {
22 struct native_convert_out_variable_generator; 22 struct native_convert_out_variable_generator;
23 struct convert_out_variable_generator; 23 struct convert_out_variable_generator;
24 struct convert_out_assign_generator; 24 struct convert_out_assign_generator;
25 struct native_convert_in_ptr_assign_generator;
26 struct convert_in_ptr_assign_generator;
25 struct native_convert_out_assign_parameterized; 27 struct native_convert_out_assign_parameterized;
26 struct native_convert_out_assign_generator; 28 struct native_convert_out_assign_generator;
27 struct convert_return_generator; 29 struct convert_return_generator;
@@ -136,6 +138,26 @@ struct attributes_needed< ::eolian_mono::convert_out_assign_generator> : std::in
136} 138}
137 139
138template <> 140template <>
141struct is_eager_generator< ::eolian_mono::native_convert_in_ptr_assign_generator> : std::true_type {};
142template <>
143struct is_generator< ::eolian_mono::native_convert_in_ptr_assign_generator> : std::true_type {};
144
145namespace type_traits {
146template <>
147struct attributes_needed< ::eolian_mono::native_convert_in_ptr_assign_generator> : std::integral_constant<int, 1> {};
148}
149
150template <>
151struct is_eager_generator< ::eolian_mono::convert_in_ptr_assign_generator> : std::true_type {};
152template <>
153struct is_generator< ::eolian_mono::convert_in_ptr_assign_generator> : std::true_type {};
154
155namespace type_traits {
156template <>
157struct attributes_needed< ::eolian_mono::convert_in_ptr_assign_generator> : std::integral_constant<int, 1> {};
158}
159
160template <>
139struct is_eager_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {}; 161struct is_eager_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {};
140template <> 162template <>
141struct is_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {}; 163struct is_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {};
@@ -341,16 +363,31 @@ inline std::string direction_modifier(attributes::parameter_def const& param)
341 } 363 }
342 else if (param.direction != attributes::parameter_direction::in) 364 else if (param.direction != attributes::parameter_direction::in)
343 { 365 {
344 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type); 366 if (param.type.c_type == "Eina_Slice" || param.type.c_type == "Eina_Rw_Slice")
345 if (param.type.c_type == "Eina_Slice" || param.type.c_type == "Eina_Rw_Slice"
346 || need_struct_conversion(regular))
347 return " ref "; 367 return " ref ";
348 else 368 else
349 return " out "; 369 return " out ";
350 } 370 }
371 else if (param.direction == attributes::parameter_direction::in && param.type.is_ptr)
372 {
373 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
374 if (need_struct_conversion(regular))
375 return " ref "; // Don't add ref on Marshal if it is ptr
376 }
351 return " "; 377 return " ";
352} 378}
353 379
380std::string marshall_direction_modifier(attributes::parameter_def const& param)
381{
382 if (param.direction == attributes::parameter_direction::in && param.type.is_ptr)
383 {
384 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
385 if (need_struct_conversion(regular) && param.type.has_own)
386 return " "; // Don't add ref on Marshal if it is ptr
387 }
388 return direction_modifier(param);
389}
390
354struct is_fp_visitor 391struct is_fp_visitor
355{ 392{
356 typedef is_fp_visitor visitor_type; 393 typedef is_fp_visitor visitor_type;
@@ -412,7 +449,7 @@ struct marshall_parameter_generator
412 449
413 if (!param.type.original_type.visit(is_fp_visitor{})) 450 if (!param.type.original_type.visit(is_fp_visitor{}))
414 return as_generator( 451 return as_generator(
415 direction_modifier(param) << marshall_type << " " << string 452 marshall_direction_modifier(param) << marshall_type << " " << string
416 ).generate(sink, std::make_tuple(param, param_name), context); 453 ).generate(sink, std::make_tuple(param, param_name), context);
417 454
418 return as_generator( 455 return as_generator(
@@ -421,14 +458,15 @@ struct marshall_parameter_generator
421 ).generate(sink, param, context); 458 ).generate(sink, param, context);
422 } 459 }
423} const marshall_parameter {}; 460} const marshall_parameter {};
424 461
462// FIXME This seems to be used only in the else branch of the native function definition. Is it really needed?
425struct argument_generator 463struct argument_generator
426{ 464{
427 template <typename OutputIterator, typename Context> 465 template <typename OutputIterator, typename Context>
428 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const 466 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
429 { 467 {
430 std::string param_name = escape_keyword(param.param_name); 468 std::string param_name = escape_keyword(param.param_name);
431 std::string direction = direction_modifier(param); 469 std::string direction = marshall_direction_modifier(param);
432 470
433 if (!param.type.original_type.visit(is_fp_visitor{})) 471 if (!param.type.original_type.visit(is_fp_visitor{}))
434 return as_generator( 472 return as_generator(
@@ -475,7 +513,7 @@ struct argument_invocation_generator
475 template <typename OutputIterator, typename Context> 513 template <typename OutputIterator, typename Context>
476 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const 514 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
477 { 515 {
478 std::string arg = direction_modifier(param); 516 std::string arg = marshall_direction_modifier(param);
479 517
480 if (use_conversion_vars && param_should_use_out_var(param, false)) 518 if (use_conversion_vars && param_should_use_out_var(param, false))
481 arg += out_variable_name(param.param_name); 519 arg += out_variable_name(param.param_name);
@@ -507,7 +545,7 @@ struct native_convert_in_variable_generator
507 return true; 545 return true;
508 546
509 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type); 547 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
510 if (param.type.is_ptr && need_pointer_conversion(regular)) 548 if (param.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion(param, regular))
511 { 549 {
512 return as_generator( 550 return as_generator(
513 "var " << string << " = eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << escape_keyword(param.param_name) << ");\n" 551 "var " << string << " = eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << escape_keyword(param.param_name) << ");\n"
@@ -575,7 +613,7 @@ struct convert_in_variable_generator
575 return true; 613 return true;
576 614
577 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type); 615 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
578 if (param.type.is_ptr && need_pointer_conversion(regular)) 616 if (param.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion(param, regular))
579 { 617 {
580 return as_generator( 618 return as_generator(
581 "var " << string << " = eina.PrimitiveConversion.ManagedToPointerAlloc(" << escape_keyword(param.param_name) << ");\n" 619 "var " << string << " = eina.PrimitiveConversion.ManagedToPointerAlloc(" << escape_keyword(param.param_name) << ");\n"
@@ -659,7 +697,8 @@ struct convert_in_variable_generator
659 } 697 }
660 698
661} const convert_in_variable {}; 699} const convert_in_variable {};
662 700
701/* Some types require an intermediate variable to be filled as out parameter in the marshalled function */
663struct convert_out_variable_generator 702struct convert_out_variable_generator
664{ 703{
665 template <typename OutputIterator, typename Context> 704 template <typename OutputIterator, typename Context>
@@ -669,7 +708,7 @@ struct convert_out_variable_generator
669 return true; 708 return true;
670 709
671 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type); 710 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
672 if (param.type.is_ptr && need_pointer_conversion(regular)) 711 if (param.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion(regular))
673 { 712 {
674 return as_generator( 713 return as_generator(
675 "System.IntPtr " << string << " = System.IntPtr.Zero;\n" 714 "System.IntPtr " << string << " = System.IntPtr.Zero;\n"
@@ -679,7 +718,7 @@ struct convert_out_variable_generator
679 { 718 {
680 return as_generator( 719 return as_generator(
681 "var " << string << " = new " << marshall_type << "();\n" 720 "var " << string << " = new " << marshall_type << "();\n"
682 ).generate(sink, std::make_tuple(out_variable_name(param.param_name), param.type), context); 721 ).generate(sink, std::make_tuple(out_variable_name(param.param_name), param), context);
683 } 722 }
684 else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT) 723 else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
685 || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT) 724 || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
@@ -742,7 +781,7 @@ struct native_convert_out_variable_generator
742 return true; 781 return true;
743 782
744 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type); 783 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
745 if (param.type.is_ptr && need_pointer_conversion(regular)) 784 if (param.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion(regular))
746 { 785 {
747 return as_generator( 786 return as_generator(
748 type << " " << string << " = default(" << type << ");\n" 787 type << " " << string << " = default(" << type << ");\n"
@@ -819,6 +858,7 @@ struct native_convert_out_variable_generator
819 858
820} const native_convert_out_variable {}; 859} const native_convert_out_variable {};
821 860
861/* Assign the Managed out variables from the marshalled intermediate ones if needed. */
822struct convert_out_assign_generator 862struct convert_out_assign_generator
823{ 863{
824 template <typename OutputIterator, typename Context> 864 template <typename OutputIterator, typename Context>
@@ -828,11 +868,17 @@ struct convert_out_assign_generator
828 return true; 868 return true;
829 869
830 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type); 870 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
831 if (param.type.is_ptr && need_pointer_conversion(regular)) 871 if (param.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion_in_return(param.type, param.direction))
832 { 872 {
833 return as_generator( 873 bool ret = as_generator(
834 string << " = eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << out_variable_name(param.param_name) << ");\n" 874 string << " = eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << out_variable_name(param.param_name) << ");\n"
835 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type), context); 875 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type), context);
876
877 if (param.type.has_own)
878 ret = ret && as_generator(scope_tab << scope_tab << "Marshal.FreeHGlobal(" << out_variable_name(param.param_name) << ");\n"
879 ).generate(sink, attributes::unused, context);
880
881 return ret;
836 } 882 }
837 else if (need_struct_conversion(regular)) 883 else if (need_struct_conversion(regular))
838 { 884 {
@@ -911,6 +957,40 @@ struct convert_out_assign_generator
911 957
912} const convert_out_assign {}; 958} const convert_out_assign {};
913 959
960struct native_convert_in_ptr_assign_generator
961{
962 template <typename OutputIterator, typename Context>
963 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
964 {
965 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
966 if (param_should_use_in_var(param, true) && param.type.is_ptr && !param.type.has_own && need_struct_conversion(regular))
967 {
968 return as_generator(
969 string << " = " << type << "_StructConvertion.ToInternal(" << in_variable_name(param.param_name) << ");\n"
970 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type), context);
971 }
972
973 return true;
974 }
975} const native_convert_in_ptr_assign {};
976
977struct convert_in_ptr_assign_generator
978{
979 template <typename OutputIterator, typename Context>
980 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
981 {
982 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
983 if (param_should_use_in_var(param, true) && param.type.is_ptr && !param.type.has_own && need_struct_conversion(regular))
984 {
985 return as_generator(
986 string << " = " << type << "_StructConvertion.ToExternal(" << in_variable_name(param.param_name) << ");\n"
987 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type), context);
988 }
989
990 return true;
991 }
992} const convert_in_ptr_assign {};
993
914struct convert_return_variable_generator 994struct convert_return_variable_generator
915{ 995{
916 template <typename OutputIterator, typename Context> 996 template <typename OutputIterator, typename Context>
@@ -923,17 +1003,19 @@ struct convert_return_variable_generator
923 1003
924} const convert_return_variable {}; 1004} const convert_return_variable {};
925 1005
926 1006/* Converts the intermediate return variable to the proper API type */
927struct convert_return_generator 1007struct convert_return_generator
928{ 1008{
929 template <typename OutputIterator, typename Context> 1009 template <typename OutputIterator, typename Context>
930 bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const 1010 bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
931 { 1011 {
932 auto regular = efl::eina::get<attributes::regular_type_def>(&ret_type.original_type); 1012 auto regular = efl::eina::get<attributes::regular_type_def>(&ret_type.original_type);
933 if (ret_type.is_ptr && need_pointer_conversion(regular)) 1013 if (ret_type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion_in_return(ret_type, attributes::parameter_direction::unknown))
934 { 1014 {
935 return as_generator( 1015 return as_generator(
936 "return eina.PrimitiveConversion.PointerToManaged<" << type << ">(_ret_var);\n" 1016 "var __ret_tmp = eina.PrimitiveConversion.PointerToManaged<" << type << ">(_ret_var);\n"
1017 << scope_tab << scope_tab << (ret_type.has_own ? ("Marshal.FreeHGlobal(_ret_var);\n"): "\n")
1018 << scope_tab << scope_tab << "return __ret_tmp;\n"
937 ).generate(sink, ret_type, context); 1019 ).generate(sink, ret_type, context);
938 } 1020 }
939 else if (need_struct_conversion(regular)) 1021 else if (need_struct_conversion(regular))
@@ -998,7 +1080,7 @@ struct native_convert_out_assign_generator
998 return true; 1080 return true;
999 1081
1000 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type); 1082 auto regular = efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
1001 if (param.type.is_ptr && need_pointer_conversion(regular)) 1083 if (param.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion_in_return(param.type, param.direction))
1002 { 1084 {
1003 return as_generator( 1085 return as_generator(
1004 string << " = eina.PrimitiveConversion.ManagedToPointerAlloc(" << string << ");\n" 1086 string << " = eina.PrimitiveConversion.ManagedToPointerAlloc(" << string << ");\n"
@@ -1131,7 +1213,7 @@ struct native_convert_return_generator
1131 bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const 1213 bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
1132 { 1214 {
1133 auto regular = efl::eina::get<attributes::regular_type_def>(&ret_type.original_type); 1215 auto regular = efl::eina::get<attributes::regular_type_def>(&ret_type.original_type);
1134 if (ret_type.is_ptr && need_pointer_conversion(regular)) 1216 if (ret_type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion_in_return(ret_type, attributes::parameter_direction::unknown) )
1135 { 1217 {
1136 return as_generator( 1218 return as_generator(
1137 "return eina.PrimitiveConversion.ManagedToPointerAlloc(_ret_var);\n" 1219 "return eina.PrimitiveConversion.ManagedToPointerAlloc(_ret_var);\n"
diff --git a/src/bin/eolian_mono/eolian/mono/struct_definition.hh b/src/bin/eolian_mono/eolian/mono/struct_definition.hh
index a0ff03315e..0b45da95b2 100644
--- a/src/bin/eolian_mono/eolian/mono/struct_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/struct_definition.hh
@@ -94,10 +94,11 @@ struct struct_internal_definition_generator
94 { 94 {
95 if (!as_generator 95 if (!as_generator
96 ( 96 (
97 "///<summary>Internal wrapper for struct " << string << ".</summary>\n"
97 "[StructLayout(LayoutKind.Sequential)]\n" 98 "[StructLayout(LayoutKind.Sequential)]\n"
98 "internal struct " << string << "\n{\n" 99 "public struct " << string << "\n{\n"
99 ) 100 )
100 .generate(sink, binding_struct_internal_name(struct_), context)) 101 .generate(sink, std::make_tuple<>(binding_struct_name(struct_), binding_struct_internal_name(struct_)), context))
101 return false; 102 return false;
102 103
103 // iterate struct fields 104 // iterate struct fields
@@ -132,6 +133,24 @@ struct struct_internal_definition_generator
132 return false; 133 return false;
133 } 134 }
134 135
136 auto external_name = binding_struct_name(struct_);
137 auto internal_name = binding_struct_internal_name(struct_);
138
139 if(!as_generator(
140 scope_tab << "///<summary>Implicit conversion to the internal/marshalling representation.</summary>\n"
141 << scope_tab << "public static implicit operator " << string << "(" << string << " struct_)\n"
142 << scope_tab << "{\n"
143 << scope_tab << scope_tab << "return " << string << "_StructConvertion.ToExternal(struct_);\n"
144 << scope_tab << "}\n"
145 << scope_tab << "///<summary>Implicit conversion to the managed representation.</summary>\n"
146 << scope_tab << "public static implicit operator " << string << "(" << string << " struct_)\n"
147 << scope_tab << "{\n"
148 << scope_tab << scope_tab << "return " << string << "_StructConvertion.ToInternal(struct_);\n"
149 << scope_tab << "}\n"
150 ).generate(sink, std::make_tuple(external_name, internal_name, external_name,
151 internal_name, external_name, external_name), context))
152 return false;
153
135 if(!as_generator("}\n").generate(sink, attributes::unused, context)) return false; 154 if(!as_generator("}\n").generate(sink, attributes::unused, context)) return false;
136 155
137 return true; 156 return true;
@@ -172,7 +191,7 @@ struct to_internal_field_convert_generator
172 .generate(sink, std::make_tuple(field_name, field_name), context)) 191 .generate(sink, std::make_tuple(field_name, field_name), context))
173 return false; 192 return false;
174 } 193 }
175 else if (field.type.is_ptr && need_pointer_conversion(regular)) 194 else if (field.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion(regular))
176 { 195 {
177 if (!as_generator( 196 if (!as_generator(
178 scope_tab << scope_tab << "_internal_struct." << string << " = eina.PrimitiveConversion.ManagedToPointerAlloc(_external_struct." << string << ");\n") 197 scope_tab << scope_tab << "_internal_struct." << string << " = eina.PrimitiveConversion.ManagedToPointerAlloc(_external_struct." << string << ");\n")
@@ -282,7 +301,7 @@ struct to_external_field_convert_generator
282 .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) 301 .generate(sink, std::make_tuple(field_name, field.type, field_name), context))
283 return false; 302 return false;
284 } 303 }
285 else if (field.type.is_ptr && need_pointer_conversion(regular)) 304 else if (field.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion(regular))
286 { 305 {
287 if (!as_generator( 306 if (!as_generator(
288 scope_tab << scope_tab << "_external_struct." << string << " = eina.PrimitiveConversion.PointerToManaged<" << type << ">(_internal_struct." << string << ");\n") 307 scope_tab << scope_tab << "_external_struct." << string << " = eina.PrimitiveConversion.PointerToManaged<" << type << ">(_internal_struct." << string << ");\n")