forked from enlightenment/efl
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.
This commit is contained in:
parent
7c543d3c86
commit
2705ea8531
|
@ -419,6 +419,7 @@ TESTS += tests/efl_mono/mono_test_driver.sh
|
||||||
|
|
||||||
tests_efl_mono_efl_mono_SOURCES = \
|
tests_efl_mono_efl_mono_SOURCES = \
|
||||||
tests/efl_mono/Main.cs \
|
tests/efl_mono/Main.cs \
|
||||||
|
tests/efl_mono/BasicDirection.cs \
|
||||||
tests/efl_mono/Eina.cs \
|
tests/efl_mono/Eina.cs \
|
||||||
tests/efl_mono/Eldbus.cs \
|
tests/efl_mono/Eldbus.cs \
|
||||||
tests/efl_mono/Eo.cs \
|
tests/efl_mono/Eo.cs \
|
||||||
|
|
|
@ -98,9 +98,11 @@ struct native_function_definition_epilogue_generator
|
||||||
if (!as_generator(
|
if (!as_generator(
|
||||||
scope_tab << scope_tab << "//Assigning out variables\n"
|
scope_tab << scope_tab << "//Assigning out variables\n"
|
||||||
<< *(scope_tab << scope_tab << native_convert_out_assign(*klass) << "\n")
|
<< *(scope_tab << scope_tab << native_convert_out_assign(*klass) << "\n")
|
||||||
|
<< scope_tab << scope_tab << "//Placeholder in ptr variables that need to be updated\n"
|
||||||
|
<< *(scope_tab << scope_tab << native_convert_in_ptr_assign << "\n")
|
||||||
<< scope_tab << scope_tab << "//Converting return variable\n"
|
<< scope_tab << scope_tab << "//Converting return variable\n"
|
||||||
<< scope_tab << scope_tab << native_convert_return(*klass)
|
<< scope_tab << scope_tab << native_convert_return(*klass)
|
||||||
).generate(sink, std::make_tuple(f.parameters, f.return_type), context))
|
).generate(sink, std::make_tuple(f.parameters, f.parameters, f.return_type), context))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -117,9 +119,11 @@ struct function_definition_epilogue_generator
|
||||||
scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
|
scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
|
||||||
<< scope_tab << scope_tab << "//Assigning out variables\n"
|
<< scope_tab << scope_tab << "//Assigning out variables\n"
|
||||||
<< *(scope_tab << scope_tab << convert_out_assign << "\n")
|
<< *(scope_tab << scope_tab << convert_out_assign << "\n")
|
||||||
|
<< scope_tab << scope_tab << "//Placeholder in ptr variables that need to be updated\n"
|
||||||
|
<< *(scope_tab << scope_tab << convert_in_ptr_assign << "\n")
|
||||||
<< scope_tab << scope_tab << "//Converting return variable\n"
|
<< scope_tab << scope_tab << "//Converting return variable\n"
|
||||||
<< scope_tab << scope_tab << convert_return
|
<< scope_tab << scope_tab << convert_return
|
||||||
).generate(sink, std::make_tuple(f.parameters, f.return_type), context))
|
).generate(sink, std::make_tuple(f.parameters, f.parameters, f.return_type), context))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -53,6 +53,30 @@ inline bool need_struct_conversion(attributes::regular_type_def const* regular)
|
||||||
return regular && regular->is_struct() && !is_struct_blacklisted(*regular);
|
return regular && regular->is_struct() && !is_struct_blacklisted(*regular);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool need_struct_conversion(attributes::parameter_def const& param, attributes::regular_type_def const* regular)
|
||||||
|
{
|
||||||
|
if (param.direction == attributes::parameter_direction::in && param.type.has_own)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return need_struct_conversion(regular);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool need_struct_conversion_in_return(attributes::type_def const& ret_type, attributes::parameter_direction const& direction)
|
||||||
|
{
|
||||||
|
auto regular = efl::eina::get<attributes::regular_type_def>(&ret_type.original_type);
|
||||||
|
|
||||||
|
if (!regular->is_struct())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (regular->is_struct() && (direction == attributes::parameter_direction::out || direction == attributes::parameter_direction::unknown))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret_type.has_own)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool need_pointer_conversion(attributes::regular_type_def const* regular)
|
inline bool need_pointer_conversion(attributes::regular_type_def const* regular)
|
||||||
{
|
{
|
||||||
if (!regular)
|
if (!regular)
|
||||||
|
|
|
@ -16,6 +16,16 @@ struct marshall_annotation_visitor_generate;
|
||||||
template <typename OutputIterator, typename Context>
|
template <typename OutputIterator, typename Context>
|
||||||
struct marshall_native_annotation_visitor_generate;
|
struct marshall_native_annotation_visitor_generate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Converts a given type/parameter to the type used in the DllImport signatures.
|
||||||
|
*
|
||||||
|
* For example, Eina.Value can be marshaled either as an eina.Value instance through
|
||||||
|
* CustomMarshallers if we have a ptr(Eina.Value) or through the intermediate
|
||||||
|
* eina.Value_Native blittable struct if it is passed by value.
|
||||||
|
*
|
||||||
|
* For details, check marshall_type_impl.h with the actual conversion rules.
|
||||||
|
*/
|
||||||
struct marshall_type_generator
|
struct marshall_type_generator
|
||||||
{
|
{
|
||||||
marshall_type_generator(bool is_return = false)
|
marshall_type_generator(bool is_return = false)
|
||||||
|
@ -26,6 +36,7 @@ struct marshall_type_generator
|
||||||
{
|
{
|
||||||
return type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr });
|
return type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr });
|
||||||
}
|
}
|
||||||
|
/* Some types may require a different conversion when they are in @out parameters. */
|
||||||
template <typename OutputIterator, typename Context>
|
template <typename OutputIterator, typename Context>
|
||||||
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
|
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
|
||||||
{
|
{
|
||||||
|
@ -36,6 +47,12 @@ struct marshall_type_generator
|
||||||
bool is_return;
|
bool is_return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generates the "[MarshalAs(...)]" rules for the given type.
|
||||||
|
*
|
||||||
|
* For example, the CustomMarshallers definitions for String and eina.Values and the
|
||||||
|
* boolean size defintion (Eina_Value is 1 byte, while C# bool has 4 bytes).
|
||||||
|
*/
|
||||||
struct marshall_annotation_generator
|
struct marshall_annotation_generator
|
||||||
{
|
{
|
||||||
marshall_annotation_generator(bool is_return = false)
|
marshall_annotation_generator(bool is_return = false)
|
||||||
|
|
|
@ -149,8 +149,10 @@ struct marshall_type_visitor_generate
|
||||||
}}
|
}}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!is_ptr && regular.is_struct() && !is_struct_blacklisted(regular))
|
if (regular.is_struct() && !is_struct_blacklisted(regular) && !(bool)(regular.base_qualifier & qualifier_info::is_own))
|
||||||
{
|
{
|
||||||
|
if ((is_out || is_return) && is_ptr)
|
||||||
|
return as_generator(" System.IntPtr").generate(sink, attributes::unused, *context);
|
||||||
return as_generator(*(lower_case[string] << ".") << string << "_StructInternal")
|
return as_generator(*(lower_case[string] << ".") << string << "_StructInternal")
|
||||||
.generate(sink, std::make_tuple(eolian_mono::escape_namespace(regular.namespaces), regular.base_type), *context);
|
.generate(sink, std::make_tuple(eolian_mono::escape_namespace(regular.namespaces), regular.base_type), *context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ namespace eolian_mono {
|
||||||
struct native_convert_out_variable_generator;
|
struct native_convert_out_variable_generator;
|
||||||
struct convert_out_variable_generator;
|
struct convert_out_variable_generator;
|
||||||
struct convert_out_assign_generator;
|
struct convert_out_assign_generator;
|
||||||
|
struct native_convert_in_ptr_assign_generator;
|
||||||
|
struct convert_in_ptr_assign_generator;
|
||||||
struct native_convert_out_assign_parameterized;
|
struct native_convert_out_assign_parameterized;
|
||||||
struct native_convert_out_assign_generator;
|
struct native_convert_out_assign_generator;
|
||||||
struct convert_return_generator;
|
struct convert_return_generator;
|
||||||
|
@ -135,6 +137,26 @@ template <>
|
||||||
struct attributes_needed< ::eolian_mono::convert_out_assign_generator> : std::integral_constant<int, 1> {};
|
struct attributes_needed< ::eolian_mono::convert_out_assign_generator> : std::integral_constant<int, 1> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct is_eager_generator< ::eolian_mono::native_convert_in_ptr_assign_generator> : std::true_type {};
|
||||||
|
template <>
|
||||||
|
struct is_generator< ::eolian_mono::native_convert_in_ptr_assign_generator> : std::true_type {};
|
||||||
|
|
||||||
|
namespace type_traits {
|
||||||
|
template <>
|
||||||
|
struct attributes_needed< ::eolian_mono::native_convert_in_ptr_assign_generator> : std::integral_constant<int, 1> {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct is_eager_generator< ::eolian_mono::convert_in_ptr_assign_generator> : std::true_type {};
|
||||||
|
template <>
|
||||||
|
struct is_generator< ::eolian_mono::convert_in_ptr_assign_generator> : std::true_type {};
|
||||||
|
|
||||||
|
namespace type_traits {
|
||||||
|
template <>
|
||||||
|
struct attributes_needed< ::eolian_mono::convert_in_ptr_assign_generator> : std::integral_constant<int, 1> {};
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct is_eager_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {};
|
struct is_eager_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
|
@ -341,16 +363,31 @@ inline std::string direction_modifier(attributes::parameter_def const& param)
|
||||||
}
|
}
|
||||||
else if (param.direction != attributes::parameter_direction::in)
|
else if (param.direction != attributes::parameter_direction::in)
|
||||||
{
|
{
|
||||||
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
if (param.type.c_type == "Eina_Slice" || param.type.c_type == "Eina_Rw_Slice")
|
||||||
if (param.type.c_type == "Eina_Slice" || param.type.c_type == "Eina_Rw_Slice"
|
|
||||||
|| need_struct_conversion(regular))
|
|
||||||
return " ref ";
|
return " ref ";
|
||||||
else
|
else
|
||||||
return " out ";
|
return " out ";
|
||||||
}
|
}
|
||||||
|
else if (param.direction == attributes::parameter_direction::in && param.type.is_ptr)
|
||||||
|
{
|
||||||
|
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
||||||
|
if (need_struct_conversion(regular))
|
||||||
|
return " ref "; // Don't add ref on Marshal if it is ptr
|
||||||
|
}
|
||||||
return " ";
|
return " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string marshall_direction_modifier(attributes::parameter_def const& param)
|
||||||
|
{
|
||||||
|
if (param.direction == attributes::parameter_direction::in && param.type.is_ptr)
|
||||||
|
{
|
||||||
|
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
||||||
|
if (need_struct_conversion(regular) && param.type.has_own)
|
||||||
|
return " "; // Don't add ref on Marshal if it is ptr
|
||||||
|
}
|
||||||
|
return direction_modifier(param);
|
||||||
|
}
|
||||||
|
|
||||||
struct is_fp_visitor
|
struct is_fp_visitor
|
||||||
{
|
{
|
||||||
typedef is_fp_visitor visitor_type;
|
typedef is_fp_visitor visitor_type;
|
||||||
|
@ -412,7 +449,7 @@ struct marshall_parameter_generator
|
||||||
|
|
||||||
if (!param.type.original_type.visit(is_fp_visitor{}))
|
if (!param.type.original_type.visit(is_fp_visitor{}))
|
||||||
return as_generator(
|
return as_generator(
|
||||||
direction_modifier(param) << marshall_type << " " << string
|
marshall_direction_modifier(param) << marshall_type << " " << string
|
||||||
).generate(sink, std::make_tuple(param, param_name), context);
|
).generate(sink, std::make_tuple(param, param_name), context);
|
||||||
|
|
||||||
return as_generator(
|
return as_generator(
|
||||||
|
@ -422,13 +459,14 @@ struct marshall_parameter_generator
|
||||||
}
|
}
|
||||||
} const marshall_parameter {};
|
} const marshall_parameter {};
|
||||||
|
|
||||||
|
// FIXME This seems to be used only in the else branch of the native function definition. Is it really needed?
|
||||||
struct argument_generator
|
struct argument_generator
|
||||||
{
|
{
|
||||||
template <typename OutputIterator, typename Context>
|
template <typename OutputIterator, typename Context>
|
||||||
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
|
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
|
||||||
{
|
{
|
||||||
std::string param_name = escape_keyword(param.param_name);
|
std::string param_name = escape_keyword(param.param_name);
|
||||||
std::string direction = direction_modifier(param);
|
std::string direction = marshall_direction_modifier(param);
|
||||||
|
|
||||||
if (!param.type.original_type.visit(is_fp_visitor{}))
|
if (!param.type.original_type.visit(is_fp_visitor{}))
|
||||||
return as_generator(
|
return as_generator(
|
||||||
|
@ -475,7 +513,7 @@ struct argument_invocation_generator
|
||||||
template <typename OutputIterator, typename Context>
|
template <typename OutputIterator, typename Context>
|
||||||
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
|
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
|
||||||
{
|
{
|
||||||
std::string arg = direction_modifier(param);
|
std::string arg = marshall_direction_modifier(param);
|
||||||
|
|
||||||
if (use_conversion_vars && param_should_use_out_var(param, false))
|
if (use_conversion_vars && param_should_use_out_var(param, false))
|
||||||
arg += out_variable_name(param.param_name);
|
arg += out_variable_name(param.param_name);
|
||||||
|
@ -507,7 +545,7 @@ struct native_convert_in_variable_generator
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
||||||
if (param.type.is_ptr && need_pointer_conversion(regular))
|
if (param.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion(param, regular))
|
||||||
{
|
{
|
||||||
return as_generator(
|
return as_generator(
|
||||||
"var " << string << " = eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << escape_keyword(param.param_name) << ");\n"
|
"var " << string << " = eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << escape_keyword(param.param_name) << ");\n"
|
||||||
|
@ -575,7 +613,7 @@ struct convert_in_variable_generator
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
||||||
if (param.type.is_ptr && need_pointer_conversion(regular))
|
if (param.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion(param, regular))
|
||||||
{
|
{
|
||||||
return as_generator(
|
return as_generator(
|
||||||
"var " << string << " = eina.PrimitiveConversion.ManagedToPointerAlloc(" << escape_keyword(param.param_name) << ");\n"
|
"var " << string << " = eina.PrimitiveConversion.ManagedToPointerAlloc(" << escape_keyword(param.param_name) << ");\n"
|
||||||
|
@ -660,6 +698,7 @@ struct convert_in_variable_generator
|
||||||
|
|
||||||
} const convert_in_variable {};
|
} const convert_in_variable {};
|
||||||
|
|
||||||
|
/* Some types require an intermediate variable to be filled as out parameter in the marshalled function */
|
||||||
struct convert_out_variable_generator
|
struct convert_out_variable_generator
|
||||||
{
|
{
|
||||||
template <typename OutputIterator, typename Context>
|
template <typename OutputIterator, typename Context>
|
||||||
|
@ -669,7 +708,7 @@ struct convert_out_variable_generator
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
||||||
if (param.type.is_ptr && need_pointer_conversion(regular))
|
if (param.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion(regular))
|
||||||
{
|
{
|
||||||
return as_generator(
|
return as_generator(
|
||||||
"System.IntPtr " << string << " = System.IntPtr.Zero;\n"
|
"System.IntPtr " << string << " = System.IntPtr.Zero;\n"
|
||||||
|
@ -679,7 +718,7 @@ struct convert_out_variable_generator
|
||||||
{
|
{
|
||||||
return as_generator(
|
return as_generator(
|
||||||
"var " << string << " = new " << marshall_type << "();\n"
|
"var " << string << " = new " << marshall_type << "();\n"
|
||||||
).generate(sink, std::make_tuple(out_variable_name(param.param_name), param.type), context);
|
).generate(sink, std::make_tuple(out_variable_name(param.param_name), param), context);
|
||||||
}
|
}
|
||||||
else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
|
else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
|
||||||
|| param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
|
|| param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
|
||||||
|
@ -742,7 +781,7 @@ struct native_convert_out_variable_generator
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
||||||
if (param.type.is_ptr && need_pointer_conversion(regular))
|
if (param.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion(regular))
|
||||||
{
|
{
|
||||||
return as_generator(
|
return as_generator(
|
||||||
type << " " << string << " = default(" << type << ");\n"
|
type << " " << string << " = default(" << type << ");\n"
|
||||||
|
@ -819,6 +858,7 @@ struct native_convert_out_variable_generator
|
||||||
|
|
||||||
} const native_convert_out_variable {};
|
} const native_convert_out_variable {};
|
||||||
|
|
||||||
|
/* Assign the Managed out variables from the marshalled intermediate ones if needed. */
|
||||||
struct convert_out_assign_generator
|
struct convert_out_assign_generator
|
||||||
{
|
{
|
||||||
template <typename OutputIterator, typename Context>
|
template <typename OutputIterator, typename Context>
|
||||||
|
@ -828,11 +868,17 @@ struct convert_out_assign_generator
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
||||||
if (param.type.is_ptr && need_pointer_conversion(regular))
|
if (param.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion_in_return(param.type, param.direction))
|
||||||
{
|
{
|
||||||
return as_generator(
|
bool ret = as_generator(
|
||||||
string << " = eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << out_variable_name(param.param_name) << ");\n"
|
string << " = eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << out_variable_name(param.param_name) << ");\n"
|
||||||
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type), context);
|
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type), context);
|
||||||
|
|
||||||
|
if (param.type.has_own)
|
||||||
|
ret = ret && as_generator(scope_tab << scope_tab << "Marshal.FreeHGlobal(" << out_variable_name(param.param_name) << ");\n"
|
||||||
|
).generate(sink, attributes::unused, context);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
else if (need_struct_conversion(regular))
|
else if (need_struct_conversion(regular))
|
||||||
{
|
{
|
||||||
|
@ -911,6 +957,40 @@ struct convert_out_assign_generator
|
||||||
|
|
||||||
} const convert_out_assign {};
|
} const convert_out_assign {};
|
||||||
|
|
||||||
|
struct native_convert_in_ptr_assign_generator
|
||||||
|
{
|
||||||
|
template <typename OutputIterator, typename Context>
|
||||||
|
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
|
||||||
|
{
|
||||||
|
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
||||||
|
if (param_should_use_in_var(param, true) && param.type.is_ptr && !param.type.has_own && need_struct_conversion(regular))
|
||||||
|
{
|
||||||
|
return as_generator(
|
||||||
|
string << " = " << type << "_StructConvertion.ToInternal(" << in_variable_name(param.param_name) << ");\n"
|
||||||
|
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type), context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} const native_convert_in_ptr_assign {};
|
||||||
|
|
||||||
|
struct convert_in_ptr_assign_generator
|
||||||
|
{
|
||||||
|
template <typename OutputIterator, typename Context>
|
||||||
|
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
|
||||||
|
{
|
||||||
|
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
||||||
|
if (param_should_use_in_var(param, true) && param.type.is_ptr && !param.type.has_own && need_struct_conversion(regular))
|
||||||
|
{
|
||||||
|
return as_generator(
|
||||||
|
string << " = " << type << "_StructConvertion.ToExternal(" << in_variable_name(param.param_name) << ");\n"
|
||||||
|
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type), context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} const convert_in_ptr_assign {};
|
||||||
|
|
||||||
struct convert_return_variable_generator
|
struct convert_return_variable_generator
|
||||||
{
|
{
|
||||||
template <typename OutputIterator, typename Context>
|
template <typename OutputIterator, typename Context>
|
||||||
|
@ -923,17 +1003,19 @@ struct convert_return_variable_generator
|
||||||
|
|
||||||
} const convert_return_variable {};
|
} const convert_return_variable {};
|
||||||
|
|
||||||
|
/* Converts the intermediate return variable to the proper API type */
|
||||||
struct convert_return_generator
|
struct convert_return_generator
|
||||||
{
|
{
|
||||||
template <typename OutputIterator, typename Context>
|
template <typename OutputIterator, typename Context>
|
||||||
bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
|
bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
|
||||||
{
|
{
|
||||||
auto regular = efl::eina::get<attributes::regular_type_def>(&ret_type.original_type);
|
auto regular = efl::eina::get<attributes::regular_type_def>(&ret_type.original_type);
|
||||||
if (ret_type.is_ptr && need_pointer_conversion(regular))
|
if (ret_type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion_in_return(ret_type, attributes::parameter_direction::unknown))
|
||||||
{
|
{
|
||||||
return as_generator(
|
return as_generator(
|
||||||
"return eina.PrimitiveConversion.PointerToManaged<" << type << ">(_ret_var);\n"
|
"var __ret_tmp = eina.PrimitiveConversion.PointerToManaged<" << type << ">(_ret_var);\n"
|
||||||
|
<< scope_tab << scope_tab << (ret_type.has_own ? ("Marshal.FreeHGlobal(_ret_var);\n"): "\n")
|
||||||
|
<< scope_tab << scope_tab << "return __ret_tmp;\n"
|
||||||
).generate(sink, ret_type, context);
|
).generate(sink, ret_type, context);
|
||||||
}
|
}
|
||||||
else if (need_struct_conversion(regular))
|
else if (need_struct_conversion(regular))
|
||||||
|
@ -998,7 +1080,7 @@ struct native_convert_out_assign_generator
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
auto regular = efl::eina::get<attributes::regular_type_def>(¶m.type.original_type);
|
||||||
if (param.type.is_ptr && need_pointer_conversion(regular))
|
if (param.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion_in_return(param.type, param.direction))
|
||||||
{
|
{
|
||||||
return as_generator(
|
return as_generator(
|
||||||
string << " = eina.PrimitiveConversion.ManagedToPointerAlloc(" << string << ");\n"
|
string << " = eina.PrimitiveConversion.ManagedToPointerAlloc(" << string << ");\n"
|
||||||
|
@ -1131,7 +1213,7 @@ struct native_convert_return_generator
|
||||||
bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
|
bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
|
||||||
{
|
{
|
||||||
auto regular = efl::eina::get<attributes::regular_type_def>(&ret_type.original_type);
|
auto regular = efl::eina::get<attributes::regular_type_def>(&ret_type.original_type);
|
||||||
if (ret_type.is_ptr && need_pointer_conversion(regular))
|
if (ret_type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion_in_return(ret_type, attributes::parameter_direction::unknown) )
|
||||||
{
|
{
|
||||||
return as_generator(
|
return as_generator(
|
||||||
"return eina.PrimitiveConversion.ManagedToPointerAlloc(_ret_var);\n"
|
"return eina.PrimitiveConversion.ManagedToPointerAlloc(_ret_var);\n"
|
||||||
|
|
|
@ -94,10 +94,11 @@ struct struct_internal_definition_generator
|
||||||
{
|
{
|
||||||
if (!as_generator
|
if (!as_generator
|
||||||
(
|
(
|
||||||
|
"///<summary>Internal wrapper for struct " << string << ".</summary>\n"
|
||||||
"[StructLayout(LayoutKind.Sequential)]\n"
|
"[StructLayout(LayoutKind.Sequential)]\n"
|
||||||
"internal struct " << string << "\n{\n"
|
"public struct " << string << "\n{\n"
|
||||||
)
|
)
|
||||||
.generate(sink, binding_struct_internal_name(struct_), context))
|
.generate(sink, std::make_tuple<>(binding_struct_name(struct_), binding_struct_internal_name(struct_)), context))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// iterate struct fields
|
// iterate struct fields
|
||||||
|
@ -132,6 +133,24 @@ struct struct_internal_definition_generator
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto external_name = binding_struct_name(struct_);
|
||||||
|
auto internal_name = binding_struct_internal_name(struct_);
|
||||||
|
|
||||||
|
if(!as_generator(
|
||||||
|
scope_tab << "///<summary>Implicit conversion to the internal/marshalling representation.</summary>\n"
|
||||||
|
<< scope_tab << "public static implicit operator " << string << "(" << string << " struct_)\n"
|
||||||
|
<< scope_tab << "{\n"
|
||||||
|
<< scope_tab << scope_tab << "return " << string << "_StructConvertion.ToExternal(struct_);\n"
|
||||||
|
<< scope_tab << "}\n"
|
||||||
|
<< scope_tab << "///<summary>Implicit conversion to the managed representation.</summary>\n"
|
||||||
|
<< scope_tab << "public static implicit operator " << string << "(" << string << " struct_)\n"
|
||||||
|
<< scope_tab << "{\n"
|
||||||
|
<< scope_tab << scope_tab << "return " << string << "_StructConvertion.ToInternal(struct_);\n"
|
||||||
|
<< scope_tab << "}\n"
|
||||||
|
).generate(sink, std::make_tuple(external_name, internal_name, external_name,
|
||||||
|
internal_name, external_name, external_name), context))
|
||||||
|
return false;
|
||||||
|
|
||||||
if(!as_generator("}\n").generate(sink, attributes::unused, context)) return false;
|
if(!as_generator("}\n").generate(sink, attributes::unused, context)) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -172,7 +191,7 @@ struct to_internal_field_convert_generator
|
||||||
.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.is_ptr && need_pointer_conversion(regular))
|
else if (field.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion(regular))
|
||||||
{
|
{
|
||||||
if (!as_generator(
|
if (!as_generator(
|
||||||
scope_tab << scope_tab << "_internal_struct." << string << " = eina.PrimitiveConversion.ManagedToPointerAlloc(_external_struct." << string << ");\n")
|
scope_tab << scope_tab << "_internal_struct." << string << " = eina.PrimitiveConversion.ManagedToPointerAlloc(_external_struct." << string << ");\n")
|
||||||
|
@ -282,7 +301,7 @@ struct to_external_field_convert_generator
|
||||||
.generate(sink, std::make_tuple(field_name, field.type, field_name), context))
|
.generate(sink, std::make_tuple(field_name, field.type, field_name), context))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (field.type.is_ptr && need_pointer_conversion(regular))
|
else if (field.type.is_ptr && need_pointer_conversion(regular) && !need_struct_conversion(regular))
|
||||||
{
|
{
|
||||||
if (!as_generator(
|
if (!as_generator(
|
||||||
scope_tab << scope_tab << "_external_struct." << string << " = eina.PrimitiveConversion.PointerToManaged<" << type << ">(_internal_struct." << string << ");\n")
|
scope_tab << scope_tab << "_external_struct." << string << " = eina.PrimitiveConversion.PointerToManaged<" << type << ">(_internal_struct." << string << ");\n")
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace TestSuite
|
||||||
|
{
|
||||||
|
|
||||||
|
class TestIntDirections
|
||||||
|
{
|
||||||
|
public static void simple_out()
|
||||||
|
{
|
||||||
|
int original = 1984;
|
||||||
|
int received;
|
||||||
|
test.Testing t = new test.TestingConcrete();
|
||||||
|
|
||||||
|
t.IntOut(original, out received);
|
||||||
|
|
||||||
|
Test.AssertEquals(-original, received);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void simple_ptr_out()
|
||||||
|
{
|
||||||
|
int original = 1984;
|
||||||
|
int received;
|
||||||
|
test.Testing t = new test.TestingConcrete();
|
||||||
|
|
||||||
|
t.IntPtrOut(original, out received);
|
||||||
|
|
||||||
|
Test.AssertEquals(original*2, received);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -266,38 +266,54 @@ class TestStructs
|
||||||
Test.Assert(r, "Function returned false");
|
Test.Assert(r, "Function returned false");
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static void simple_ptr_in()
|
public static void simple_ptr_in()
|
||||||
// {
|
{
|
||||||
// var simple = structSimpleWithValues();
|
var simple = structSimpleWithValues();
|
||||||
// test.Testing t = new test.TestingConcrete();
|
int original = simple.Fint;
|
||||||
// bool r = t.struct_simple_ptr_in(simple);
|
simple.Fstring = "Struct Ptr In";
|
||||||
// Test.Assert(r, "Function returned false");
|
test.Testing t = new test.TestingConcrete();
|
||||||
// }
|
Test.Assert(t.StructSimplePtrIn(ref simple));
|
||||||
|
Test.AssertEquals(-original, simple.Fint);
|
||||||
|
Test.AssertEquals("nI rtP tcurtS", simple.Fstring);
|
||||||
|
}
|
||||||
|
|
||||||
// public static void simple_ptr_in_own()
|
public static void simple_ptr_in_own()
|
||||||
// {
|
{
|
||||||
// var simple = structSimpleWithValues();
|
var simple = structSimpleWithValues();
|
||||||
// test.Testing t = new test.TestingConcrete();
|
int original = simple.Fint;
|
||||||
// bool r = t.struct_simple_ptr_in_own(simple);
|
simple.Fstring = "Struct Ptr In Own";
|
||||||
// Test.Assert(r, "Function returned false");
|
test.Testing t = new test.TestingConcrete();
|
||||||
// }
|
test.StructSimple result = t.StructSimplePtrInOwn(ref simple);
|
||||||
|
Test.AssertEquals(-original, result.Fint);
|
||||||
|
Test.AssertEquals("nwO nI rtP tcurtS", result.Fstring);
|
||||||
|
}
|
||||||
|
|
||||||
public static void simple_out()
|
public static void simple_out()
|
||||||
{
|
{
|
||||||
var simple = new test.StructSimple();
|
var simple = new test.StructSimple();
|
||||||
test.Testing t = new test.TestingConcrete();
|
test.Testing t = new test.TestingConcrete();
|
||||||
bool r = t.StructSimpleOut(ref simple);
|
bool r = t.StructSimpleOut(out simple);
|
||||||
Test.Assert(r, "Function returned false");
|
Test.Assert(r, "Function returned false");
|
||||||
checkStructSimple(simple);
|
checkStructSimple(simple);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static void simple_ptr_out()
|
public static void simple_ptr_out()
|
||||||
// {
|
{
|
||||||
// }
|
test.StructSimple simple;
|
||||||
|
test.Testing t = new test.TestingConcrete();
|
||||||
|
test.StructSimple result = t.StructSimplePtrOut(out simple);
|
||||||
|
Test.AssertEquals(result.Fint, simple.Fint);
|
||||||
|
Test.AssertEquals(result.Fstring, simple.Fstring);
|
||||||
|
}
|
||||||
|
|
||||||
// public static void simple_ptr_out_own()
|
public static void simple_ptr_out_own()
|
||||||
// {
|
{
|
||||||
// }
|
test.StructSimple simple;
|
||||||
|
test.Testing t = new test.TestingConcrete();
|
||||||
|
test.StructSimple result = t.StructSimplePtrOutOwn(out simple);
|
||||||
|
Test.AssertEquals(result.Fint, simple.Fint);
|
||||||
|
Test.AssertEquals(simple.Fstring, "Ptr Out Own");
|
||||||
|
}
|
||||||
|
|
||||||
public static void simple_return()
|
public static void simple_return()
|
||||||
{
|
{
|
||||||
|
@ -306,14 +322,186 @@ class TestStructs
|
||||||
checkStructSimple(simple);
|
checkStructSimple(simple);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static void simple_ptr_return()
|
public static void simple_ptr_return()
|
||||||
// {
|
{
|
||||||
// }
|
test.Testing t = new test.TestingConcrete();
|
||||||
|
var simple = t.StructSimplePtrReturn();
|
||||||
|
Test.AssertEquals(simple.Fstring, "Ret Ptr");
|
||||||
|
}
|
||||||
|
|
||||||
// public static void simple_ptr_return_own()
|
public static void simple_ptr_return_own()
|
||||||
// {
|
{
|
||||||
// }
|
test.Testing t = new test.TestingConcrete();
|
||||||
|
var simple = t.StructSimplePtrReturnOwn();
|
||||||
|
Test.AssertEquals(simple.Fstring, "Ret Ptr Own");
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StructReturner : test.TestingInherit
|
||||||
|
{
|
||||||
|
public test.StructSimple received;
|
||||||
|
public bool called;
|
||||||
|
|
||||||
|
public StructReturner() : base(null)
|
||||||
|
{
|
||||||
|
called = false;
|
||||||
|
received = default(test.StructSimple);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool StructSimpleIn(test.StructSimple simple)
|
||||||
|
{
|
||||||
|
called = true;
|
||||||
|
received = simple;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool StructSimplePtrIn(ref test.StructSimple simple)
|
||||||
|
{
|
||||||
|
called = true;
|
||||||
|
simple.Fstring = "Virtual Struct Ptr In";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override test.StructSimple StructSimplePtrInOwn(ref test.StructSimple simple)
|
||||||
|
{
|
||||||
|
called = true;
|
||||||
|
received = simple;
|
||||||
|
return received;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool StructSimpleOut(out test.StructSimple simple) {
|
||||||
|
called = true;
|
||||||
|
simple = new test.StructSimple();
|
||||||
|
simple.Fstring = "Virtual Struct Out";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override test.StructSimple StructSimplePtrOut(out test.StructSimple simple) {
|
||||||
|
called = true;
|
||||||
|
// No way to explicitly define the ownership of the parameter.
|
||||||
|
simple = new test.StructSimple();
|
||||||
|
simple.Fstring = "Virtual Struct Ptr Out";
|
||||||
|
return simple;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override test.StructSimple StructSimplePtrOutOwn(out test.StructSimple simple) {
|
||||||
|
called = true;
|
||||||
|
// No way to explicitly define the ownership of the parameter.
|
||||||
|
simple = new test.StructSimple();
|
||||||
|
simple.Fstring = "Virtual Struct Ptr Out Own";
|
||||||
|
return simple;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override test.StructSimple StructSimpleReturn()
|
||||||
|
{
|
||||||
|
called = true;
|
||||||
|
var simple = new test.StructSimple();
|
||||||
|
simple.Fstring = "Virtual Struct Return";
|
||||||
|
return simple;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override test.StructSimple StructSimplePtrReturn()
|
||||||
|
{
|
||||||
|
called = true;
|
||||||
|
var simple = new test.StructSimple();
|
||||||
|
simple.Fstring = "Virtual Struct Ptr Return";
|
||||||
|
return simple;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override test.StructSimple StructSimplePtrReturnOwn()
|
||||||
|
{
|
||||||
|
called = true;
|
||||||
|
var simple = new test.StructSimple();
|
||||||
|
simple.Fstring = "Virtual Struct Ptr Return Own";
|
||||||
|
return simple;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void simple_in_virtual()
|
||||||
|
{
|
||||||
|
StructReturner t = new StructReturner();
|
||||||
|
var simple = structSimpleWithValues();
|
||||||
|
simple.Fstring = "Virtual Struct In";
|
||||||
|
|
||||||
|
t.CallStructSimpleIn(simple);
|
||||||
|
Test.Assert(t.called);
|
||||||
|
Test.AssertEquals(simple.Fstring, t.received.Fstring);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void simple_ptr_in_virtual()
|
||||||
|
{
|
||||||
|
StructReturner t = new StructReturner();
|
||||||
|
var simple = structSimpleWithValues();
|
||||||
|
string reference = "Virtual Struct Ptr In";
|
||||||
|
|
||||||
|
t.CallStructSimplePtrIn(ref simple);
|
||||||
|
Test.Assert(t.called);
|
||||||
|
Test.AssertEquals(simple.Fstring, reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void simple_ptr_in_own_virtual()
|
||||||
|
{
|
||||||
|
StructReturner t = new StructReturner();
|
||||||
|
var simple = structSimpleWithValues();
|
||||||
|
simple.Fstring = "Virtual Struct Ptr In Own";
|
||||||
|
|
||||||
|
t.CallStructSimplePtrInOwn(ref simple);
|
||||||
|
Test.Assert(t.called);
|
||||||
|
Test.AssertEquals(t.received.Fstring, simple.Fstring);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void simple_out_virtual()
|
||||||
|
{
|
||||||
|
StructReturner t = new StructReturner();
|
||||||
|
test.StructSimple simple;
|
||||||
|
t.CallStructSimpleOut(out simple);
|
||||||
|
Test.Assert(t.called, "override was not called");
|
||||||
|
Test.AssertEquals("Virtual Struct Out", simple.Fstring);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void simple_ptr_out_virtual()
|
||||||
|
{
|
||||||
|
StructReturner t = new StructReturner();
|
||||||
|
test.StructSimple simple;
|
||||||
|
t.CallStructSimplePtrOut(out simple);
|
||||||
|
Test.Assert(t.called, "override was not called");
|
||||||
|
Test.AssertEquals("Virtual Struct Ptr Out", simple.Fstring);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void simple_ptr_out_own_virtual()
|
||||||
|
{
|
||||||
|
StructReturner t = new StructReturner();
|
||||||
|
test.StructSimple simple;
|
||||||
|
t.CallStructSimplePtrOutOwn(out simple);
|
||||||
|
Test.Assert(t.called, "override was not called");
|
||||||
|
Test.AssertEquals("Virtual Struct Ptr Out Own", simple.Fstring);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void simple_return_virtual()
|
||||||
|
{
|
||||||
|
StructReturner t = new StructReturner();
|
||||||
|
test.StructSimple simple = t.CallStructSimpleReturn();
|
||||||
|
Test.Assert(t.called, "override was not called");
|
||||||
|
Test.AssertEquals("Virtual Struct Return", simple.Fstring);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void simple_ptr_return_virtual()
|
||||||
|
{
|
||||||
|
StructReturner t = new StructReturner();
|
||||||
|
test.StructSimple simple = t.CallStructSimplePtrReturn();
|
||||||
|
Test.Assert(t.called, "override was not called");
|
||||||
|
Test.AssertEquals("Virtual Struct Ptr Return", simple.Fstring);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void simple_ptr_return_own_virtual()
|
||||||
|
{
|
||||||
|
StructReturner t = new StructReturner();
|
||||||
|
test.StructSimple simple = t.CallStructSimplePtrReturnOwn();
|
||||||
|
Test.Assert(t.called, "override was not called");
|
||||||
|
Test.AssertEquals("Virtual Struct Ptr Return Own", simple.Fstring);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complex Structs
|
||||||
public static void complex_in()
|
public static void complex_in()
|
||||||
{
|
{
|
||||||
var complex = structComplexWithValues();
|
var complex = structComplexWithValues();
|
||||||
|
@ -334,7 +522,7 @@ class TestStructs
|
||||||
{
|
{
|
||||||
var complex = new test.StructComplex();
|
var complex = new test.StructComplex();
|
||||||
test.Testing t = new test.TestingConcrete();
|
test.Testing t = new test.TestingConcrete();
|
||||||
bool r = t.StructComplexOut(ref complex);
|
bool r = t.StructComplexOut(out complex);
|
||||||
Test.Assert(r, "Function returned false");
|
Test.Assert(r, "Function returned false");
|
||||||
checkStructComplex(complex);
|
checkStructComplex(complex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,8 @@ typedef struct Test_Testing_Data
|
||||||
Eina_Free_Cb free_cb;
|
Eina_Free_Cb free_cb;
|
||||||
Eina_Error error_code;
|
Eina_Error error_code;
|
||||||
Eina_Value *stored_value;
|
Eina_Value *stored_value;
|
||||||
|
Test_StructSimple stored_struct;
|
||||||
|
int stored_int;
|
||||||
} Test_Testing_Data;
|
} Test_Testing_Data;
|
||||||
|
|
||||||
typedef struct Test_Numberwrapper_Data
|
typedef struct Test_Numberwrapper_Data
|
||||||
|
@ -100,6 +101,17 @@ Efl_Object *_test_testing_return_object(Eo *obj, EINA_UNUSED Test_Testing_Data *
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _test_testing_int_out(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, int x, int *y)
|
||||||
|
{
|
||||||
|
*y = -x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _test_testing_int_ptr_out(EINA_UNUSED Eo *obj, Test_Testing_Data *pd, int x, int **y)
|
||||||
|
{
|
||||||
|
pd->stored_int = x * 2;
|
||||||
|
*y = &pd->stored_int;
|
||||||
|
}
|
||||||
|
|
||||||
const char *_test_testing_in_string(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, const char *str)
|
const char *_test_testing_in_string(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, const char *str)
|
||||||
{
|
{
|
||||||
const char *ret = malloc(sizeof(char)*(strlen(str) + 1));
|
const char *ret = malloc(sizeof(char)*(strlen(str) + 1));
|
||||||
|
@ -3342,20 +3354,34 @@ Eina_Bool _test_testing_struct_simple_in(EINA_UNUSED Eo *obj, EINA_UNUSED Test_T
|
||||||
return check_and_modify_struct_simple(&simple);
|
return check_and_modify_struct_simple(&simple);
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN
|
static void _reverse_string(char *str)
|
||||||
Eina_Bool _test_testing_struct_simple_ptr_in(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple *simple)
|
|
||||||
{
|
{
|
||||||
(void) simple;
|
int len = strlen(str);
|
||||||
EINA_LOG_ERR("Not implemented!");
|
if (len > 0) {
|
||||||
return EINA_FALSE;
|
for (int i=0, k=len-1; i < len/2; i++, k--) {
|
||||||
|
char tmp = str[k];
|
||||||
|
str[k] = str[i];
|
||||||
|
str[i] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN
|
EOLIAN
|
||||||
Eina_Bool _test_testing_struct_simple_ptr_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple *simple)
|
Eina_Bool _test_testing_struct_simple_ptr_in(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple *simple)
|
||||||
{
|
{
|
||||||
(void) simple;
|
simple->fint = -simple->fint;
|
||||||
EINA_LOG_ERR("Not implemented!");
|
_reverse_string(simple->fstring);
|
||||||
return EINA_FALSE;
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN
|
||||||
|
Test_StructSimple _test_testing_struct_simple_ptr_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple *simple)
|
||||||
|
{
|
||||||
|
Test_StructSimple ret = *simple;
|
||||||
|
free(simple);
|
||||||
|
ret.fint = -ret.fint;
|
||||||
|
_reverse_string(ret.fstring);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN
|
EOLIAN
|
||||||
|
@ -3373,19 +3399,20 @@ Eina_Bool _test_testing_struct_simple_out(EINA_UNUSED Eo *obj, EINA_UNUSED Test_
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN
|
EOLIAN
|
||||||
Eina_Bool _test_testing_struct_simple_ptr_out(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple **simple)
|
Test_StructSimple _test_testing_struct_simple_ptr_out(EINA_UNUSED Eo *obj, Test_Testing_Data *pd, Test_StructSimple **simple)
|
||||||
{
|
{
|
||||||
(void) simple;
|
struct_simple_with_values(&pd->stored_struct);
|
||||||
EINA_LOG_ERR("Not implemented!");
|
*simple = &pd->stored_struct;
|
||||||
return EINA_FALSE;
|
return **simple;
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN
|
EOLIAN
|
||||||
Eina_Bool _test_testing_struct_simple_ptr_out_own(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple **simple)
|
Test_StructSimple _test_testing_struct_simple_ptr_out_own(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple **simple)
|
||||||
{
|
{
|
||||||
(void) simple;
|
*simple = malloc(sizeof(Test_StructSimple));
|
||||||
EINA_LOG_ERR("Not implemented!");
|
struct_simple_with_values(*simple);
|
||||||
return EINA_FALSE;
|
(*simple)->fstring = "Ptr Out Own";
|
||||||
|
return **simple;
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN
|
EOLIAN
|
||||||
|
@ -3399,15 +3426,72 @@ Test_StructSimple _test_testing_struct_simple_return(EINA_UNUSED Eo *obj, EINA_U
|
||||||
EOLIAN
|
EOLIAN
|
||||||
Test_StructSimple *_test_testing_struct_simple_ptr_return(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd)
|
Test_StructSimple *_test_testing_struct_simple_ptr_return(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd)
|
||||||
{
|
{
|
||||||
EINA_LOG_ERR("Not implemented!");
|
struct_simple_with_values(&pd->stored_struct);
|
||||||
return NULL;
|
pd->stored_struct.fstring = "Ret Ptr";
|
||||||
|
return &pd->stored_struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN
|
EOLIAN
|
||||||
Test_StructSimple *_test_testing_struct_simple_ptr_return_own(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd)
|
Test_StructSimple *_test_testing_struct_simple_ptr_return_own(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd)
|
||||||
{
|
{
|
||||||
EINA_LOG_ERR("Not implemented!");
|
Test_StructSimple *ret = malloc(sizeof(Test_StructSimple));
|
||||||
return NULL;
|
struct_simple_with_values(ret);
|
||||||
|
ret->fstring = "Ret Ptr Own";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN
|
||||||
|
void _test_testing_call_struct_simple_in(Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple simple)
|
||||||
|
{
|
||||||
|
test_testing_struct_simple_in(obj, simple);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN
|
||||||
|
void _test_testing_call_struct_simple_ptr_in(Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple *simple)
|
||||||
|
{
|
||||||
|
test_testing_struct_simple_ptr_in(obj, simple);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN
|
||||||
|
void _test_testing_call_struct_simple_ptr_in_own(Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple *simple)
|
||||||
|
{
|
||||||
|
test_testing_struct_simple_ptr_in_own(obj, simple);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN
|
||||||
|
void _test_testing_call_struct_simple_out(Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple *simple)
|
||||||
|
{
|
||||||
|
test_testing_struct_simple_out(obj, simple);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN
|
||||||
|
void _test_testing_call_struct_simple_ptr_out(Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple **simple)
|
||||||
|
{
|
||||||
|
test_testing_struct_simple_ptr_out(obj, simple);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN
|
||||||
|
void _test_testing_call_struct_simple_ptr_out_own(Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple **simple)
|
||||||
|
{
|
||||||
|
test_testing_struct_simple_ptr_out_own(obj, simple);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN
|
||||||
|
Test_StructSimple _test_testing_call_struct_simple_return(Eo *obj, EINA_UNUSED Test_Testing_Data *pd)
|
||||||
|
{
|
||||||
|
return test_testing_struct_simple_return(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN
|
||||||
|
Test_StructSimple *_test_testing_call_struct_simple_ptr_return(Eo *obj, EINA_UNUSED Test_Testing_Data *pd)
|
||||||
|
{
|
||||||
|
return test_testing_struct_simple_ptr_return(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN
|
||||||
|
Test_StructSimple *_test_testing_call_struct_simple_ptr_return_own(Eo *obj, EINA_UNUSED Test_Testing_Data *pd)
|
||||||
|
{
|
||||||
|
return test_testing_struct_simple_ptr_return_own(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
// with complex types
|
// with complex types
|
||||||
|
|
|
@ -87,6 +87,20 @@ class Test.Testing (Efl.Object) {
|
||||||
return: Test.Testing;
|
return: Test.Testing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int_out {
|
||||||
|
params {
|
||||||
|
@in x: int;
|
||||||
|
@out y: int;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int_ptr_out {
|
||||||
|
params {
|
||||||
|
@in x: int;
|
||||||
|
@out y: ptr(int);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
in_stringshare {
|
in_stringshare {
|
||||||
params {
|
params {
|
||||||
@in v: stringshare;
|
@in v: stringshare;
|
||||||
|
@ -1355,19 +1369,19 @@ class Test.Testing (Efl.Object) {
|
||||||
return: bool;
|
return: bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct_simple_ptr_in {
|
struct_simple_ptr_in {
|
||||||
// params {
|
params {
|
||||||
// @in simple: ptr(Test.StructSimple);
|
@in simple: ptr(Test.StructSimple);
|
||||||
// }
|
}
|
||||||
// return: bool;
|
return: bool;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// struct_simple_ptr_in_own {
|
struct_simple_ptr_in_own {
|
||||||
// params {
|
params {
|
||||||
// @in simple: ptr(Test.StructSimple) @owned;
|
@in simple: ptr(Test.StructSimple) @owned;
|
||||||
// }
|
}
|
||||||
// return: bool;
|
return: Test.StructSimple;
|
||||||
// }
|
}
|
||||||
|
|
||||||
struct_simple_out {
|
struct_simple_out {
|
||||||
params {
|
params {
|
||||||
|
@ -1376,31 +1390,79 @@ class Test.Testing (Efl.Object) {
|
||||||
return: bool;
|
return: bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct_simple_ptr_out {
|
struct_simple_ptr_out {
|
||||||
// params {
|
params {
|
||||||
// @out simple: ptr(Test.StructSimple);
|
@out simple: ptr(Test.StructSimple);
|
||||||
// }
|
}
|
||||||
// return: bool;
|
return: Test.StructSimple;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// struct_simple_ptr_out_own {
|
struct_simple_ptr_out_own {
|
||||||
// params {
|
params {
|
||||||
// @out simple: ptr(Test.StructSimple) @owned;
|
@out simple: ptr(Test.StructSimple) @owned;
|
||||||
// }
|
}
|
||||||
// return: bool;
|
return: Test.StructSimple;
|
||||||
// }
|
}
|
||||||
|
|
||||||
struct_simple_return {
|
struct_simple_return {
|
||||||
return: Test.StructSimple;
|
return: Test.StructSimple;
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct_simple_ptr_return {
|
struct_simple_ptr_return {
|
||||||
// return: ptr(Test.StructSimple);
|
return: ptr(Test.StructSimple);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// struct_simple_ptr_return_own {
|
struct_simple_ptr_return_own {
|
||||||
// return: ptr(Test.StructSimple) @owned;
|
return: ptr(Test.StructSimple) @owned;
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
call_struct_simple_in {
|
||||||
|
params {
|
||||||
|
@in simple: Test.StructSimple;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
call_struct_simple_ptr_in {
|
||||||
|
params {
|
||||||
|
@in simple: ptr(Test.StructSimple);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
call_struct_simple_ptr_in_own {
|
||||||
|
params {
|
||||||
|
@in simple: ptr(Test.StructSimple) @owned;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
call_struct_simple_out {
|
||||||
|
params {
|
||||||
|
@out simple: Test.StructSimple;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
call_struct_simple_ptr_out {
|
||||||
|
params {
|
||||||
|
@out simple: ptr(Test.StructSimple);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
call_struct_simple_ptr_out_own {
|
||||||
|
params {
|
||||||
|
@out simple: ptr(Test.StructSimple) @owned;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
call_struct_simple_return {
|
||||||
|
return: Test.StructSimple;
|
||||||
|
}
|
||||||
|
|
||||||
|
call_struct_simple_ptr_return {
|
||||||
|
return: ptr(Test.StructSimple);
|
||||||
|
}
|
||||||
|
|
||||||
|
call_struct_simple_ptr_return_own {
|
||||||
|
return: ptr(Test.StructSimple) @owned;
|
||||||
|
}
|
||||||
|
|
||||||
struct_complex_in {
|
struct_complex_in {
|
||||||
params {
|
params {
|
||||||
|
@ -1409,19 +1471,19 @@ class Test.Testing (Efl.Object) {
|
||||||
return: bool;
|
return: bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct_complex_ptr_in {
|
struct_complex_ptr_in {
|
||||||
// params {
|
params {
|
||||||
// @in complex: ptr(Test.StructComplex);
|
@in complex: ptr(Test.StructComplex);
|
||||||
// }
|
}
|
||||||
// return: bool;
|
return: bool;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// struct_complex_ptr_in_own {
|
struct_complex_ptr_in_own {
|
||||||
// params {
|
params {
|
||||||
// @in complex: ptr(Test.StructComplex) @owned;
|
@in complex: ptr(Test.StructComplex) @owned;
|
||||||
// }
|
}
|
||||||
// return: bool;
|
return: bool;
|
||||||
// }
|
}
|
||||||
|
|
||||||
struct_complex_out {
|
struct_complex_out {
|
||||||
params {
|
params {
|
||||||
|
|
Loading…
Reference in New Issue