diff --git a/src/Makefile_Efl_Mono.am b/src/Makefile_Efl_Mono.am index 72a1916515..ad45a22b81 100644 --- a/src/Makefile_Efl_Mono.am +++ b/src/Makefile_Efl_Mono.am @@ -371,6 +371,7 @@ tests_efl_mono_efl_mono_exe_SOURCES = \ tests/efl_mono/Events.cs \ tests/efl_mono/FunctionPointers.cs \ tests/efl_mono/Strings.cs \ + tests/efl_mono/Structs.cs \ tests/efl_mono/TestUtils.cs \ tests/efl_mono/Value.cs \ tests/efl_mono/ValueEolian.cs diff --git a/src/bin/eolian_mono/eolian/mono/function_pointer.hh b/src/bin/eolian_mono/eolian/mono/function_pointer.hh index 84fdb79881..0f91a4c41c 100644 --- a/src/bin/eolian_mono/eolian/mono/function_pointer.hh +++ b/src/bin/eolian_mono/eolian/mono/function_pointer.hh @@ -69,14 +69,14 @@ struct function_pointer { << scope_tab << "public " << type << " ManagedCb(" << (parameter % ",") << ")\n" << scope_tab << "{\n" - << scope_tab << scope_tab << (f.return_type.c_type != "void" ? "return ": "") << "_cb(_cb_data, " << (argument_invocation % ", ") << ");\n" + << scope_tab << scope_tab << (f.return_type.c_type != "void" ? "return ": "") << "_cb(_cb_data, " << (argument_invocation_no_conversion % ", ") << ");\n" << scope_tab << "}\n\n" << scope_tab << "public static " << type << " Cb(IntPtr cb_data, " << (parameter % ", ") << ")\n" << scope_tab << "{\n" << scope_tab << scope_tab << "GCHandle handle = GCHandle.FromIntPtr(cb_data);\n" << scope_tab << scope_tab << string << " cb = (" << string << ")handle.Target;\n" - << scope_tab << scope_tab << (f.return_type.c_type != "void" ? "return " : "") << "cb(" << (argument_invocation % ", ") << ");\n" + << scope_tab << scope_tab << (f.return_type.c_type != "void" ? "return " : "") << "cb(" << (argument_invocation_no_conversion % ", ") << ");\n" << scope_tab << "}\n" << "}\n" ).generate(sink, std::make_tuple(f.return_type, f.parameters, f.parameters, f.return_type, f.parameters, f_name, f_name, f.parameters), context)) diff --git a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh index f220c94cb6..8563afcb12 100644 --- a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh +++ b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh @@ -10,6 +10,7 @@ struct class_context concrete, inherit, inherit_native, + structs, }; wrapper_kind current_wrapper_kind; }; diff --git a/src/bin/eolian_mono/eolian/mono/helpers.hh b/src/bin/eolian_mono/eolian/mono/helpers.hh new file mode 100644 index 0000000000..28b54a5aef --- /dev/null +++ b/src/bin/eolian_mono/eolian/mono/helpers.hh @@ -0,0 +1,59 @@ +#ifndef EOLIAN_MONO_HELPERS_HH +#define EOLIAN_MONO_HELPERS_HH + +#include "grammar/klass_def.hpp" + +namespace eolian_mono { + +namespace attributes = efl::eolian::grammar::attributes; + +inline std::string type_full_name(attributes::regular_type_def const& type) +{ + std::string full_name; + for (auto& name : type.namespaces) + { + full_name += name + "."; + } + full_name += type.base_type; + return full_name; +} + +inline std::string struct_full_name(attributes::struct_def const& struct_) +{ + std::string full_name; + for (auto& name : struct_.namespaces) + { + full_name += name + "."; + } + full_name += struct_.cxx_name; + return full_name; +} + +// Blacklist structs that require some kind of manual binding. +inline bool is_struct_blacklisted(std::string const& full_name) +{ + return full_name == "Efl.Event.Description" + // || full_name == "Eina.File" + || full_name == "Eina.Binbuf" + || full_name == "Eina.Slice" + || full_name == "Eina.Rw_Slice"; +} + +inline bool is_struct_blacklisted(attributes::struct_def const& struct_) +{ + return is_struct_blacklisted(struct_full_name(struct_)); +} + +inline bool is_struct_blacklisted(attributes::regular_type_def const& struct_) +{ + return is_struct_blacklisted(type_full_name(struct_)); +} + +inline bool need_struct_conversion(attributes::regular_type_def const* regular) +{ + return regular && regular->is_struct() && !is_struct_blacklisted(*regular); +} + +} + +#endif diff --git a/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh b/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh index 2765dcdc25..8774cd855c 100644 --- a/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh +++ b/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh @@ -51,7 +51,7 @@ struct marshall_annotation_visitor_generate match const parameter_match_table[] = { // signed primitives - {"bool", nullptr, [&] { return " [MarshalAs(UnmanagedType.I1)]"; }}, + {"bool", nullptr, [&] { return " [MarshalAs(UnmanagedType.U1)]"; }}, {"string", true, [&] { return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]"; }}, @@ -80,7 +80,7 @@ struct marshall_annotation_visitor_generate match const return_match_table[] = { // signed primitives - {"bool", nullptr, [&] { return " [return: MarshalAs(UnmanagedType.I1)]"; }}, + {"bool", nullptr, [&] { return " [return: MarshalAs(UnmanagedType.U1)]"; }}, {"string", true, [&] { return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]"; }}, @@ -170,7 +170,7 @@ struct marshall_native_annotation_visitor_generate match const parameter_match_table[] = { // signed primitives - {"bool", nullptr, [&] { return " [MarshalAs(UnmanagedType.I1)]"; }}, + {"bool", nullptr, [&] { return " [MarshalAs(UnmanagedType.U1)]"; }}, {"string", true, [&] { return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]"; }}, @@ -191,7 +191,7 @@ struct marshall_native_annotation_visitor_generate match const return_match_table[] = { // signed primitives - {"bool", nullptr, [&] { return " [return: MarshalAs(UnmanagedType.I1)]"; }}, + {"bool", nullptr, [&] { return " [return: MarshalAs(UnmanagedType.U1)]"; }}, {"string", true, [&] { return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]"; }}, 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 caeb17f83f..7950b31213 100644 --- a/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh +++ b/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh @@ -4,6 +4,7 @@ #include "grammar/generator.hpp" #include "grammar/klass_def.hpp" #include "grammar/case.hpp" +#include "helpers.hh" #include "namespace.hh" #include "type_impl.hh" #include "generation_contexts.hh" @@ -148,7 +149,12 @@ struct marshall_type_visitor_generate }} }; - if(eina::optional b = call_match + if (regular.is_struct() && !is_struct_blacklisted(regular)) + { + return as_generator(*(lower_case[string] << ".") << string << "_StructInternal") + .generate(sink, std::make_tuple(eolian_mono::escape_namespace(regular.namespaces), regular.base_type), *context); + } + else if (eina::optional b = call_match (match_table , [&] (match const& m) { diff --git a/src/bin/eolian_mono/eolian/mono/parameter.hh b/src/bin/eolian_mono/eolian/mono/parameter.hh index e9aa957ad7..0e3fa326d5 100644 --- a/src/bin/eolian_mono/eolian/mono/parameter.hh +++ b/src/bin/eolian_mono/eolian/mono/parameter.hh @@ -4,6 +4,7 @@ #include "grammar/generator.hpp" #include "grammar/klass_def.hpp" #include "grammar/case.hpp" +#include "helpers.hh" #include "marshall_type.hh" #include "type.hh" #include "using_decl.hh" @@ -226,6 +227,9 @@ inline bool param_is_acceptable(attributes::parameter_def const ¶m, std::str inline bool param_should_use_out_var(attributes::parameter_def const& param, bool native) { + if (param.direction == attributes::parameter_direction::in) + return false; + if ((native && param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT)) || (native && param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT)) || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT) @@ -261,11 +265,18 @@ inline bool param_should_use_out_var(attributes::parameter_def const& param, boo ) return true; + auto regular = efl::eina::get(¶m.type.original_type); + if (need_struct_conversion(regular)) + return true; + return false; } inline bool param_should_use_in_var(attributes::parameter_def const& param, bool /*native*/) { + if (param.direction != attributes::parameter_direction::in) + return false; + 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, "const Eina_Binbuf *", !WANT_OWN, !WANT_OUT) @@ -299,6 +310,10 @@ inline bool param_should_use_in_var(attributes::parameter_def const& param, bool ) return true; + auto regular = efl::eina::get(¶m.type.original_type); + if (need_struct_conversion(regular)) + return true; + return false; } @@ -320,7 +335,9 @@ inline std::string direction_modifier(attributes::parameter_def const& param) } else if (param.direction != attributes::parameter_direction::in) { - if (param.type.c_type == "Eina_Slice" || param.type.c_type == "Eina_Rw_Slice") + auto regular = efl::eina::get(¶m.type.original_type); + if (param.type.c_type == "Eina_Slice" || param.type.c_type == "Eina_Rw_Slice" + || need_struct_conversion(regular)) return " ref "; else return " out "; @@ -335,7 +352,7 @@ struct is_fp_visitor bool operator()(grammar::attributes::regular_type_def const &type) const { - return type.is_function_ptr; + return type.is_function_ptr(); } template @@ -445,14 +462,18 @@ struct native_argument_invocation_generator // Generates the correct parameter name when invoking a function struct argument_invocation_generator { + constexpr argument_invocation_generator(bool conversion_vars) + : use_conversion_vars(conversion_vars) + {} + template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { std::string arg = direction_modifier(param); - if (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); - else if (param_should_use_in_var(param, false)) + else if (use_conversion_vars && param_should_use_in_var(param, false)) arg += in_variable_name(param.param_name); else if (param.type.original_type.visit(is_fp_visitor{})) { @@ -465,7 +486,11 @@ struct argument_invocation_generator return as_generator(arg).generate(sink, attributes::unused, context); } -} const argument_invocation {}; + + bool const use_conversion_vars; +} const argument_invocation {true}; + +argument_invocation_generator const argument_invocation_no_conversion {false}; struct native_convert_in_variable_generator { @@ -475,7 +500,14 @@ struct native_convert_in_variable_generator if (param.direction != attributes::parameter_direction::in) return true; - if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *") + auto regular = efl::eina::get(¶m.type.original_type); + if (need_struct_conversion(regular)) + { + return as_generator( + "var " << string << " = " << type << "_StructConvertion.ToExternal(" << escape_keyword(param.param_name) << ");\n" + ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context); + } + else if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *") { return as_generator( "var " << string << " = new eina.Binbuf(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false") << ");\n" @@ -530,7 +562,14 @@ struct convert_in_variable_generator if (param.direction != attributes::parameter_direction::in) return true; - if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *") + auto regular = efl::eina::get(¶m.type.original_type); + if (need_struct_conversion(regular)) + { + return as_generator( + "var " << string << " = " << type << "_StructConvertion.ToInternal(" << escape_keyword(param.param_name) << ");\n" + ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context); + } + else if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *") { auto var_name = in_variable_name(param.param_name); if (!as_generator( @@ -608,7 +647,17 @@ struct convert_out_variable_generator template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { - if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT) + if (param.direction == attributes::parameter_direction::in) + return true; + + auto regular = efl::eina::get(¶m.type.original_type); + if (need_struct_conversion(regular)) + { + return as_generator( + "var " << string << " = new " << marshall_type << "();\n" + ).generate(sink, std::make_tuple(out_variable_name(param.param_name), param.type), context); + } + 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, "const Eina_Binbuf *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT) @@ -665,7 +714,12 @@ struct native_convert_out_variable_generator template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { - if (param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT) + if (param.direction == attributes::parameter_direction::in) + return true; + + auto regular = efl::eina::get(¶m.type.original_type); + if (need_struct_conversion(regular) + || param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT)) { return as_generator( @@ -740,7 +794,17 @@ struct convert_out_assign_generator template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { - if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT) + if (param.direction == attributes::parameter_direction::in) + return true; + + auto regular = efl::eina::get(¶m.type.original_type); + if (need_struct_conversion(regular)) + { + return as_generator( + string << " = " << type << "_StructConvertion.ToExternal(" << out_variable_name(param.param_name) << ");\n" + ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type), context); + } + 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, "const Eina_Binbuf *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT) @@ -829,7 +893,14 @@ struct convert_return_generator template bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const { - if (ret_type.c_type == "Eina_Binbuf *" || ret_type.c_type == "const Eina_Binbuf *") + auto regular = efl::eina::get(&ret_type.original_type); + if (need_struct_conversion(regular)) + { + return as_generator( + "return " << type << "_StructConvertion.ToExternal(_ret_var);\n" + ).generate(sink, ret_type, context); + } + else if (ret_type.c_type == "Eina_Binbuf *" || ret_type.c_type == "const Eina_Binbuf *") { if (!as_generator("var _binbuf_ret = new eina.Binbuf(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"} << ");\n" << scope_tab << scope_tab << "return _binbuf_ret;\n") @@ -881,7 +952,17 @@ struct native_convert_out_assign_generator template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { - if (param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT)) + if (param.direction == attributes::parameter_direction::in) + return true; + + auto regular = efl::eina::get(¶m.type.original_type); + if (need_struct_conversion(regular)) + { + return as_generator( + string << " = " << type << "_StructConvertion.ToInternal(" << string << ");\n" + ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context); + } + else if (param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT)) { return as_generator( string << "= efl.eo.Globals.cached_stringshare_to_intptr(((" << string << "Inherit)wrapper).cached_stringshares, " << string << ");\n" @@ -1001,7 +1082,14 @@ struct native_convert_return_generator template bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const { - if (ret_type.c_type == "const char *") + auto regular = efl::eina::get(&ret_type.original_type); + if (need_struct_conversion(regular)) + { + return as_generator( + "return " << type << "_StructConvertion.ToInternal(_ret_var);\n" + ).generate(sink, ret_type, context); + } + else if (ret_type.c_type == "const char *") { if(!ret_type.has_own) { diff --git a/src/bin/eolian_mono/eolian/mono/struct_definition.hh b/src/bin/eolian_mono/eolian/mono/struct_definition.hh index ee05852904..62992357f2 100644 --- a/src/bin/eolian_mono/eolian/mono/struct_definition.hh +++ b/src/bin/eolian_mono/eolian/mono/struct_definition.hh @@ -6,28 +6,28 @@ #include "grammar/indentation.hpp" #include "grammar/list.hpp" #include "grammar/alternative.hpp" +#include "helpers.hh" #include "type.hh" #include "keyword.hh" #include "using_decl.hh" namespace eolian_mono { -// Blacklist structs that require some kind of manual binding. -static bool is_struct_blacklisted(attributes::struct_def const& struct_) +inline std::string binding_struct_name(attributes::struct_def const& struct_) { - std::string full_name; + return struct_.cxx_name; +} - for (auto it=struct_.namespaces.begin(); it != struct_.namespaces.end(); it++) - { - full_name += *it + "."; - } +inline std::string binding_struct_internal_name(attributes::struct_def const& struct_) +{ + return struct_.cxx_name + "_StructInternal"; +} - full_name += struct_.cxx_name; - return full_name == "Efl.Event.Description" - || full_name == "Eina.File" - || full_name == "Eina.Binbuf" - || full_name == "Eina.Slice" - || full_name == "Eina.Rw_Slice"; +inline std::string to_field_name(std::string const& in) +{ + std::string field_name = in; + field_name[0] = std::toupper(field_name[0]); // Hack to allow 'static' as a field name + return field_name; } struct struct_definition_generator @@ -35,33 +35,22 @@ struct struct_definition_generator template bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const { - if (is_struct_blacklisted(struct_)) - return true; - - std::vector cpp_namespaces = escape_namespace(attributes::cpp_namespaces(struct_.namespaces)); - - auto open_namespace = *("namespace " << string << " { ") << "\n"; - if(!as_generator(open_namespace).generate(sink, cpp_namespaces, add_lower_case_context(context))) return false; - if(!as_generator ( + "[StructLayout(LayoutKind.Sequential)]\n" "public struct " << string << "\n{\n" ) - .generate(sink, struct_.cxx_name, context)) + .generate(sink, binding_struct_name(struct_), context)) return false; // iterate struct fields - for(auto first = std::begin(struct_.fields) - , last = std::end(struct_.fields); first != last; ++first) + for (auto const& field : struct_.fields) { - auto field_name = (*first).name; - auto field_type = (*first).type; - field_name[0] = std::toupper(field_name[0]); // Hack to allow 'static' as a field name if (!as_generator ( - "public " << type << " " << string << ";\n" + " public " << type << " " << string << ";\n" ) - .generate(sink, std::make_tuple(field_type, field_name), context)) + .generate(sink, std::make_tuple(field.type, to_field_name(field.name)), context)) return false; } @@ -77,14 +66,354 @@ struct struct_definition_generator if(!as_generator("}\n").generate(sink, attributes::unused, context)) return false; + return true; + } +} const struct_definition {}; + + +struct struct_internal_definition_generator +{ + template + bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const + { + if (!as_generator + ( + "[StructLayout(LayoutKind.Sequential)]\n" + "public struct " << string << "\n{\n" + ) + .generate(sink, binding_struct_internal_name(struct_), context)) + return false; + + // iterate struct fields + for (auto const& field : struct_.fields) + { + auto field_name = to_field_name(field.name); + auto klass = efl::eina::get(&field.type.original_type); + auto regular = efl::eina::get(&field.type.original_type); + + if (klass + || (regular && (regular->base_type == "string" + || regular->base_type == "mstring" + || regular->base_type == "stringshare" + || regular->base_type == "any_value_ptr"))) + { + if (!as_generator(" public System.IntPtr " << string << ";\n") + .generate(sink, field_name, context)) + return false; + } + else if (!as_generator(eolian_mono::marshall_annotation(false) << " public " << eolian_mono::marshall_type(false) << " " << string << ";\n") + .generate(sink, std::make_tuple(field.type, field.type, field_name), context)) + return false; + } + + // Check whether this is an extern struct without declared fields in .eo file and generate a + // placeholder field if positive. + // Mono's JIT is picky when generating function pointer for delegates with empty structs, leading to + // those 'mini-amd64.c condition fields not met' crashes. + if (struct_.fields.size() == 0) + { + if (!as_generator("public IntPtr field;\n").generate(sink, nullptr, context)) + return false; + } + + if(!as_generator("}\n").generate(sink, attributes::unused, context)) return false; + + return true; + } +} const struct_internal_definition {}; + + +// Conversors generation // + +struct to_internal_field_convert_generator +{ + template + bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const + { + auto field_name = to_field_name(field.name); + auto regular = efl::eina::get(&field.type.original_type); + auto klass = efl::eina::get(&field.type.original_type); + auto complex = efl::eina::get(&field.type.original_type); + + if (klass) + { + if (!as_generator( + scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << ".raw_handle;\n") + .generate(sink, std::make_tuple(field_name, field_name), context)) + return false; + } + else if ((complex && (complex->outer.base_type == "array" + || complex->outer.base_type == "inarray" + || complex->outer.base_type == "list" + || complex->outer.base_type == "inlist" + || complex->outer.base_type == "iterator" + || complex->outer.base_type == "hash")) + || field.type.c_type == "Eina_Binbuf *" || field.type.c_type == "const Eina_Binbuf *") + { + // Always assumes pointer + if (!as_generator( + scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << ".Handle;\n") + .generate(sink, std::make_tuple(field_name, field_name), context)) + return false; + } + else if (need_struct_conversion(regular)) + { + if (!as_generator( + scope_tab << scope_tab << "_internal_struct." << string << " = " << type << "_StructConvertion.ToInternal(_external_struct." << string << ");\n") + .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) + return false; + } + else if (regular && (regular->base_type == "string" || regular->base_type == "mstring")) + { + if (!as_generator( + scope_tab << scope_tab << "_internal_struct." << string << " = eina.MemoryNative.StrDup(_external_struct." << string << ");\n") + .generate(sink, std::make_tuple(field_name, field_name), context)) + return false; + } + else if (regular && regular->base_type == "stringshare") + { + if (!as_generator( + scope_tab << scope_tab << "_internal_struct." << string << " = eina.Stringshare.eina_stringshare_add(_external_struct." << string << ");\n") + .generate(sink, std::make_tuple(field_name, field_name), context)) + return false; + } + else if (field.type.c_type == "Eina_Slice" || field.type.c_type == "const Eina_Slice" + || field.type.c_type == "Eina_Rw_Slice" || field.type.c_type == "const Eina_Rw_Slice") + { + if (!as_generator( + "\n" << + scope_tab << scope_tab << "_internal_struct." << field_name << ".Len = _external_struct." << field_name << ".Len;\n" << + scope_tab << scope_tab << "_internal_struct." << field_name << ".Mem = _external_struct." << field_name << ".Mem;\n\n") + .generate(sink, attributes::unused, context)) + return false; + } + else if (field.type.c_type == "Eina_Value" || field.type.c_type == "const Eina_Value") + { + if (!as_generator( + scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << ".GetNative();\n" + ).generate(sink, std::make_tuple(field_name, field_name), context)) + return false; + } + else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *") + { + if (!as_generator( + scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << ".Handle;\n" + ).generate(sink, std::make_tuple(field_name, field_name), context)) + return false; + } + else // primitives and enums + { + if (!as_generator( + scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << ";\n") + .generate(sink, std::make_tuple(field_name, field_name), context)) + return false; + } + return true; + } +} const to_internal_field_convert {}; + +struct to_external_field_convert_generator +{ + template + bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const + { + auto field_name = to_field_name(field.name); + auto regular = efl::eina::get(&field.type.original_type); + auto klass = efl::eina::get(&field.type.original_type); + auto complex = efl::eina::get(&field.type.original_type); + + if (klass) + { + if (!as_generator( + "\n" + << scope_tab << scope_tab << "_external_struct." << string + << " = (" << type << ") System.Activator.CreateInstance(typeof(" + << type << "Concrete), new System.Object[] {_internal_struct." << string << "});\n" + << scope_tab << scope_tab << "efl.eo.Globals.efl_ref(_internal_struct." << string << ");\n\n") + .generate(sink, std::make_tuple(field_name, field.type, field.type, field_name, field_name), context)) + return false; + } + else if (field.type.c_type == "Eina_Binbuf *" || field.type.c_type == "const Eina_Binbuf *") + { + if (!as_generator( + scope_tab << scope_tab << "_external_struct." << string << " = new " << type << "(_internal_struct." << string << ", false);\n") + .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) + return false; + } + else if (complex && (complex->outer.base_type == "array" + || complex->outer.base_type == "inarray" + || complex->outer.base_type == "list" + || complex->outer.base_type == "inlist" + || complex->outer.base_type == "iterator")) + { + // Always assumes pointer + if (!as_generator( + scope_tab << scope_tab << "_external_struct." << string << " = new " << type << "(_internal_struct." << string << ", false, false);\n") + .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) + return false; + } + else if (complex && complex->outer.base_type == "hash") + { + if (!as_generator( + scope_tab << scope_tab << "_external_struct." << string << " = new " << type << "(_internal_struct." << string << ", false, false, false);\n") + .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) + return false; + } + else if (need_struct_conversion(regular)) + { + if (!as_generator( + scope_tab << scope_tab << "_external_struct." << string << " = " << type << "_StructConvertion.ToExternal(_internal_struct." << string << ");\n") + .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) + return false; + } + else if (regular && (regular->base_type == "string" || regular->base_type == "mstring" || regular->base_type == "stringshare")) + { + if (!as_generator( + scope_tab << scope_tab << "_external_struct." << string << " = eina.StringConversion.NativeUtf8ToManagedString(_internal_struct." << string << ");\n") + .generate(sink, std::make_tuple(field_name, field_name), context)) + return false; + } + else if (field.type.c_type == "Eina_Slice" || field.type.c_type == "const Eina_Slice" + || field.type.c_type == "Eina_Rw_Slice" || field.type.c_type == "const Eina_Rw_Slice") + { + if (!as_generator( + "\n" << + scope_tab << scope_tab << "_external_struct." << field_name << ".Len = _internal_struct." << field_name << ".Len;\n" << + scope_tab << scope_tab << "_external_struct." << field_name << ".Mem = _internal_struct." << field_name << ".Mem;\n\n") + .generate(sink, attributes::unused, context)) + return false; + } + else if (field.type.c_type == "Eina_Value" || field.type.c_type == "const Eina_Value") + { + if (!as_generator( + scope_tab << scope_tab << "_external_struct." << string << " = new eina.Value(_internal_struct." << string << ");\n" + ).generate(sink, std::make_tuple(field_name, field_name), context)) + return false; + } + else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *") + { + if (!as_generator( + scope_tab << scope_tab << "_external_struct." << string << " = new eina.Value(_internal_struct." << string << ", eina.ValueOwnership.Unmanaged);\n" + ).generate(sink, std::make_tuple(field_name, field_name), context)) + return false; + } + else // primitives and enums + { + if (!as_generator( + scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << ";\n") + .generate(sink, std::make_tuple(field_name, field_name), context)) + return false; + } + return true; + } +} const to_external_field_convert {}; + +struct struct_binding_conversion_functions_generator +{ + template + bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const + { + // Open conversion class + if (!as_generator + ( + "public static class " << string << "_StructConvertion\n{\n" + ) + .generate(sink, struct_.cxx_name, context)) + return false; + + // to internal + if (!as_generator + ( + scope_tab << "public static " << string << " ToInternal(" << string << " _external_struct)\n" + << scope_tab << "{\n" + << scope_tab << scope_tab << "var _internal_struct = new " << string << "();\n\n" + ) + .generate(sink, std::make_tuple(binding_struct_internal_name(struct_) + , binding_struct_name(struct_) + , binding_struct_internal_name(struct_) + ), context)) + return false; + + for (auto const& field : struct_.fields) + { + if (!to_internal_field_convert.generate(sink, field, context)) + return false; + } + + if (!as_generator + ( + "\n" + << scope_tab << scope_tab << "return _internal_struct;\n" + << scope_tab << "}\n\n" + ) + .generate(sink, attributes::unused, context)) + return false; + + // to external + if (!as_generator + ( + scope_tab << "public static " << string << " ToExternal(" << string << " _internal_struct)\n" + << scope_tab << "{\n" + << scope_tab << scope_tab << "var _external_struct = new " << string << "();\n\n" + ) + .generate(sink, std::make_tuple(binding_struct_name(struct_) + , binding_struct_internal_name(struct_) + , binding_struct_name(struct_) + ), context)) + return false; + + for (auto const& field : struct_.fields) + { + if (!to_external_field_convert.generate(sink, field, context)) + return false; + } + + if (!as_generator + ( + "\n" + << scope_tab << scope_tab << "return _external_struct;\n" + << scope_tab << "}\n\n" + ) + .generate(sink, attributes::unused, context)) + return false; + + // Close conversion class + if (!as_generator("}\n").generate(sink, attributes::unused, context)) + return false; + + return true; + } +} const struct_binding_conversion_functions {}; + +struct struct_entities_generator +{ + template + bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const + { + if (is_struct_blacklisted(struct_)) + return true; + + std::vector cpp_namespaces = escape_namespace(attributes::cpp_namespaces(struct_.namespaces)); + + auto open_namespace = *("namespace " << string << " { ") << "\n"; + if (!as_generator(open_namespace).generate(sink, cpp_namespaces, add_lower_case_context(context))) + return false; + + if (!struct_definition.generate(sink, struct_, context)) + return false; + + if (!struct_internal_definition.generate(sink, struct_, context)) + return false; + + if (!struct_binding_conversion_functions.generate(sink, struct_, context)) + return false; + auto close_namespace = *(lit("} ")) << "\n"; if(!as_generator(close_namespace).generate(sink, cpp_namespaces, context)) return false; return true; } -}; - -struct_definition_generator const struct_definition = {}; +} const struct_entities {}; } @@ -95,9 +424,49 @@ struct is_eager_generator< ::eolian_mono::struct_definition_generator> : std::tr template <> struct is_generator< ::eolian_mono::struct_definition_generator> : std::true_type {}; +template <> +struct is_eager_generator< ::eolian_mono::struct_internal_definition_generator> : std::true_type {}; +template <> +struct is_generator< ::eolian_mono::struct_internal_definition_generator> : std::true_type {}; + +template <> +struct is_eager_generator< ::eolian_mono::to_internal_field_convert_generator> : std::true_type {}; +template <> +struct is_generator< ::eolian_mono::to_internal_field_convert_generator> : std::true_type {}; + +template <> +struct is_eager_generator< ::eolian_mono::to_external_field_convert_generator> : std::true_type {}; +template <> +struct is_generator< ::eolian_mono::to_external_field_convert_generator> : std::true_type {}; + +template <> +struct is_eager_generator< ::eolian_mono::struct_binding_conversion_functions_generator> : std::true_type {}; +template <> +struct is_generator< ::eolian_mono::struct_binding_conversion_functions_generator> : std::true_type {}; + +template <> +struct is_eager_generator< ::eolian_mono::struct_entities_generator> : std::true_type {}; +template <> +struct is_generator< ::eolian_mono::struct_entities_generator> : std::true_type {}; + namespace type_traits { template <> struct attributes_needed< ::eolian_mono::struct_definition_generator> : std::integral_constant {}; + +template <> +struct attributes_needed< ::eolian_mono::struct_internal_definition_generator> : std::integral_constant {}; + +template <> +struct attributes_needed< ::eolian_mono::to_internal_field_convert_generator> : std::integral_constant {}; + +template <> +struct attributes_needed< ::eolian_mono::to_external_field_convert_generator> : std::integral_constant {}; + +template <> +struct attributes_needed< ::eolian_mono::struct_binding_conversion_functions_generator> : std::integral_constant {}; + +template <> +struct attributes_needed< ::eolian_mono::struct_entities_generator> : std::integral_constant {}; } } } } diff --git a/src/bin/eolian_mono/eolian/mono/type_impl.hh b/src/bin/eolian_mono/eolian/mono/type_impl.hh index d6d753b88d..3d3950c172 100644 --- a/src/bin/eolian_mono/eolian/mono/type_impl.hh +++ b/src/bin/eolian_mono/eolian/mono/type_impl.hh @@ -13,12 +13,28 @@ namespace eina = efl::eina; template T const* as_const_pointer(T* p) { return p; } +inline attributes::regular_type_def replace_base_type(attributes::regular_type_def v, std::string name) { v.base_type = name; return v; } +template +attributes::regular_type_def replace_base_integer(attributes::regular_type_def v) +{ + bool s = std::is_signed::value; + switch (sizeof(T)) + { + case 1: return s ? replace_base_type(v, " sbyte") : replace_base_type(v, " byte"); + case 2: return s ? replace_base_type(v, " short") : replace_base_type(v, " ushort"); + case 4: return s ? replace_base_type(v, " int") : replace_base_type(v, " uint"); + case 8: return s ? replace_base_type(v, " long") : replace_base_type(v, " ulong"); + default: return v; + } +} + +inline attributes::complex_type_def replace_outer(attributes::complex_type_def v, attributes::regular_type_def const& regular) { v.outer = regular; @@ -62,26 +78,29 @@ struct visitor_generate const match_table[] = { // signed primitives - {"byte", nullptr, [&] { return replace_base_type(regular, " byte"); }} - , {"llong", nullptr, [&] { return replace_base_type(regular, " long"); }} - , {"int8", nullptr, [&] { return replace_base_type(regular, " byte"); }} + {"byte", nullptr, [&] { return replace_base_type(regular, " sbyte"); }} + , {"short", nullptr, [&] { return replace_base_integer(regular); }} + , {"int", nullptr, [&] { return replace_base_integer(regular); }} + , {"long", nullptr, [&] { return replace_base_integer(regular); }} + , {"llong", nullptr, [&] { return replace_base_integer(regular); }} + , {"int8", nullptr, [&] { return replace_base_type(regular, " sbyte"); }} , {"int16", nullptr, [&] { return replace_base_type(regular, " short"); }} , {"int32", nullptr, [&] { return replace_base_type(regular, " int"); }} , {"int64", nullptr, [&] { return replace_base_type(regular, " long"); }} - , {"ssize", nullptr, [&] { return replace_base_type(regular, " long"); }} + , {"ssize", nullptr, [&] { return replace_base_integer(regular); }} // unsigned primitives , {"ubyte", nullptr, [&] { return replace_base_type(regular, " byte"); }} - , {"ushort", nullptr, [&] { return replace_base_type(regular, " ushort"); }} - , {"uint", nullptr, [&] { return replace_base_type(regular, " uint"); }} - , {"ulong", nullptr, [&] { return replace_base_type(regular, " ulong"); }} - , {"ullong", nullptr, [&] { return replace_base_type(regular, " ulong"); }} + , {"ushort", nullptr, [&] { return replace_base_integer(regular); }} + , {"uint", nullptr, [&] { return replace_base_integer(regular); }} + , {"ulong", nullptr, [&] { return replace_base_integer(regular); }} + , {"ullong", nullptr, [&] { return replace_base_integer(regular); }} , {"uint8", nullptr, [&] { return replace_base_type(regular, " byte"); }} , {"uint16", nullptr, [&] { return replace_base_type(regular, " ushort"); }} , {"uint32", nullptr, [&] { return replace_base_type(regular, " uint"); }} , {"uint64", nullptr, [&] { return replace_base_type(regular, " ulong"); }} - , {"size", nullptr, [&] { return replace_base_type(regular, " ulong"); }} + , {"size", nullptr, [&] { return replace_base_integer(regular); }} - , {"ptrdiff", nullptr, [&] { return replace_base_type(regular, " long"); }} + , {"ptrdiff", nullptr, [&] { return replace_base_integer(regular); }} , {"intptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr"); }} , {"void_ptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr"); }} , {"void", nullptr, [&] diff --git a/src/bin/eolian_mono/eolian_mono.cc b/src/bin/eolian_mono/eolian_mono.cc index 43eebfc1f2..db50906318 100644 --- a/src/bin/eolian_mono/eolian_mono.cc +++ b/src/bin/eolian_mono/eolian_mono.cc @@ -183,7 +183,8 @@ run(options_type const& opts) , struct_last; struct_iterator != struct_last; ++struct_iterator) { efl::eolian::grammar::attributes::struct_def struct_(&*struct_iterator, opts.unit); - if (!eolian_mono::struct_definition.generate(iterator, struct_, efl::eolian::grammar::context_null())) + auto structs_cxt = context_add_tag(class_context{class_context::structs}, context); + if (!eolian_mono::struct_entities.generate(iterator, struct_, structs_cxt)) { throw std::runtime_error("Failed to generate struct"); } diff --git a/src/bindings/mono/efl_mono/.gitignore b/src/bindings/mono/efl_mono/.gitignore index cc8a6c3119..ebc334c1d4 100644 --- a/src/bindings/mono/efl_mono/.gitignore +++ b/src/bindings/mono/efl_mono/.gitignore @@ -1 +1,2 @@ /efl_libs.cs +/efl_libs.csv diff --git a/src/bindings/mono/eina_mono/eina_value.cs b/src/bindings/mono/eina_mono/eina_value.cs index 1c9a78ce8d..15c06590fa 100644 --- a/src/bindings/mono/eina_mono/eina_value.cs +++ b/src/bindings/mono/eina_mono/eina_value.cs @@ -681,7 +681,7 @@ public class Value : IDisposable, IComparable, IEquatable this.Ownership = ValueOwnership.Managed; } - internal Value(IntPtr handle, ValueOwnership ownership=ValueOwnership.Managed) { + public Value(IntPtr handle, ValueOwnership ownership=ValueOwnership.Managed) { this.Handle = handle; this.Ownership = ownership; } diff --git a/src/bindings/mono/eo_mono/workaround.cs b/src/bindings/mono/eo_mono/workaround.cs index 7e338de8ef..d29ce3969f 100644 --- a/src/bindings/mono/eo_mono/workaround.cs +++ b/src/bindings/mono/eo_mono/workaround.cs @@ -59,7 +59,10 @@ namespace efl { namespace kw_event { [StructLayout(LayoutKind.Sequential)] public struct Description { - IntPtr pointer; // Opaque type, just pass the pointer. What about hot/freeze/etc? + public IntPtr Name; + [MarshalAs(UnmanagedType.U1)] public bool Unfreezable; + [MarshalAs(UnmanagedType.U1)] public bool Legacy_is; + [MarshalAs(UnmanagedType.U1)] public bool Restart; private static Dictionary descriptions = new Dictionary(); @@ -76,7 +79,10 @@ public struct Description { descriptions.Add(name, data); } - this.pointer = descriptions[name]; + this.Name = descriptions[name]; + this.Unfreezable = false; + this.Legacy_is = false; + this.Restart = false; } }; @@ -241,6 +247,7 @@ public struct Efl_Font_Size { namespace eina { +[StructLayout(LayoutKind.Sequential)] public struct Rectangle { public int x; public int y; @@ -250,12 +257,6 @@ public struct Rectangle { } -namespace eina { - -public interface File {} - -} - namespace evas { /* Copied from Evas_Legacy.h */ diff --git a/src/lib/eolian_cxx/grammar/converting_argument.hpp b/src/lib/eolian_cxx/grammar/converting_argument.hpp index eb7ef57376..c419d36b7c 100644 --- a/src/lib/eolian_cxx/grammar/converting_argument.hpp +++ b/src/lib/eolian_cxx/grammar/converting_argument.hpp @@ -26,7 +26,7 @@ struct converting_argument_generator bool operator()(T const&) const { return false;} bool operator()(attributes::regular_type_def const& r) const { - return r.is_function_ptr; + return r.is_function_ptr(); } } static const is_function_ptr; template diff --git a/src/lib/eolian_cxx/grammar/klass_def.hpp b/src/lib/eolian_cxx/grammar/klass_def.hpp index d1fce8f6d9..f95b765cee 100644 --- a/src/lib/eolian_cxx/grammar/klass_def.hpp +++ b/src/lib/eolian_cxx/grammar/klass_def.hpp @@ -24,7 +24,7 @@ namespace efl { namespace eolian { namespace grammar { namespace attributes { struct complex_type_def; - + } namespace attributes { @@ -64,16 +64,44 @@ bool lexicographical_compare(std::tuple const& lhs || (!(std::get<0>(rhs) < std::get<0>(lhs)) && std::get<1>(lhs) < std::get<1>(rhs)); } - + +enum class typedecl_type +{ + unknown, + struct_, + struct_opaque, + enum_, + alias, + function_ptr, +}; + +inline typedecl_type typedecl_type_get(Eolian_Typedecl const* decl) +{ + if (!decl) + return typedecl_type::unknown; + + Eolian_Typedecl_Type t = eolian_typedecl_type_get(decl); + switch (t) + { + case EOLIAN_TYPEDECL_UNKNOWN: return typedecl_type::unknown; + case EOLIAN_TYPEDECL_STRUCT: return typedecl_type::struct_; + case EOLIAN_TYPEDECL_STRUCT_OPAQUE: return typedecl_type::struct_opaque; + case EOLIAN_TYPEDECL_ENUM: return typedecl_type::enum_; + case EOLIAN_TYPEDECL_ALIAS: return typedecl_type::alias; + case EOLIAN_TYPEDECL_FUNCTION_POINTER: return typedecl_type::function_ptr; + default: return typedecl_type::unknown; + } +} + struct type_def; bool operator==(type_def const& rhs, type_def const& lhs); bool operator!=(type_def const& rhs, type_def const& lhs); - + enum class class_type { regular, abstract_, mixin, interface_ }; - + struct klass_name { std::vector namespaces; @@ -168,19 +196,28 @@ get(klass_name const& klass) { return tuple_element::get(klass); } - + struct regular_type_def { - regular_type_def() : is_undefined(false), is_function_ptr(false) {} + regular_type_def() : type_type(typedecl_type::unknown), is_undefined(false) {} regular_type_def(std::string base_type, qualifier_def qual, std::vector namespaces - , bool is_undefined = false, bool is_function_ptr = false) + , typedecl_type type_type = typedecl_type::unknown, bool is_undefined = false) : base_type(std::move(base_type)), base_qualifier(qual), namespaces(std::move(namespaces)) - , is_undefined(is_undefined), is_function_ptr(is_function_ptr) {} - + , type_type(type_type), is_undefined(is_undefined) {} + + bool is_type(typedecl_type tt) const { return type_type == tt; } + bool is_unknown() const { return is_type(typedecl_type::unknown); } + bool is_struct() const { return is_type(typedecl_type::struct_); } + bool is_struct_opaque() const { return is_type(typedecl_type::struct_opaque); } + bool is_enum() const { return is_type(typedecl_type::enum_); } + bool is_alias() const { return is_type(typedecl_type::alias); } + bool is_function_ptr() const { return is_type(typedecl_type::function_ptr); } + std::string base_type; qualifier_def base_qualifier; std::vector namespaces; - bool is_undefined, is_function_ptr; + typedecl_type type_type; + bool is_undefined; }; inline bool operator==(regular_type_def const& rhs, regular_type_def const& lhs) @@ -245,7 +282,7 @@ struct get_qualifier_visitor return complex.outer.base_qualifier; } }; - + inline bool operator==(type_def const& lhs, type_def const& rhs) { return lhs.original_type == rhs.original_type && lhs.c_type == rhs.c_type; @@ -254,9 +291,9 @@ inline bool operator!=(type_def const& lhs, type_def const& rhs) { return !(lhs == rhs); } - -type_def const void_ {attributes::regular_type_def{"void", {qualifier_info::is_none, {}}, {}, false}, "void", false}; - + +type_def const void_ {attributes::regular_type_def{"void", {qualifier_info::is_none, {}}, {}}, "void", false}; + inline void type_def::set(Eolian_Type const* eolian_type, Eolian_Unit const* unit, Eolian_C_Type_Type ctype) { c_type = ::eolian_type_c_type_get(unit, eolian_type, ctype); @@ -267,14 +304,14 @@ inline void type_def::set(Eolian_Type const* eolian_type, Eolian_Unit const* uni switch( ::eolian_type_type_get(eolian_type)) { case EOLIAN_TYPE_VOID: - original_type = attributes::regular_type_def{"void", {qualifiers(eolian_type), {}}, {}, false}; + original_type = attributes::regular_type_def{"void", {qualifiers(eolian_type), {}}, {}}; break; case EOLIAN_TYPE_REGULAR: if (!stp) { bool is_undefined = false; Eolian_Typedecl const* decl = eolian_type_typedecl_get(unit, eolian_type); - bool is_function_ptr = decl && eolian_typedecl_type_get(decl) == EOLIAN_TYPEDECL_FUNCTION_POINTER; + typedecl_type type_type = (decl ? typedecl_type_get(decl) : typedecl_type::unknown); if(decl && eolian_typedecl_type_get(decl) == EOLIAN_TYPEDECL_ALIAS) { Eolian_Type const* aliased = eolian_typedecl_base_type_get(decl); @@ -289,7 +326,7 @@ inline void type_def::set(Eolian_Type const* eolian_type, Eolian_Unit const* uni for(efl::eina::iterator namespace_iterator( ::eolian_type_namespaces_get(eolian_type)) , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator) namespaces.push_back(&*namespace_iterator); - original_type = {regular_type_def{ ::eolian_type_name_get(eolian_type), {qualifiers(eolian_type), {}}, namespaces, is_undefined, is_function_ptr}}; + original_type = {regular_type_def{ ::eolian_type_name_get(eolian_type), {qualifiers(eolian_type), {}}, namespaces, type_type, is_undefined}}; } else { @@ -320,7 +357,7 @@ inline void type_def::set(Eolian_Expression_Type eolian_exp_type) switch(eolian_exp_type) { case EOLIAN_EXPR_INT: - original_type = attributes::regular_type_def{"int", {{}, {}}, {}, false}; + original_type = attributes::regular_type_def{"int", {{}, {}}, {}}; c_type = "int"; break; default: @@ -351,7 +388,7 @@ struct add_optional_qualifier_visitor } }; } - + struct parameter_def { parameter_direction direction; @@ -369,7 +406,7 @@ struct parameter_def { return !(lhs == rhs); } - + parameter_def(parameter_direction direction, type_def type, std::string param_name, Eolian_Unit const* unit) : direction(std::move(direction)), type(std::move(type)), param_name(std::move(param_name)), unit(unit) {} parameter_def(Eolian_Function_Parameter const* param, Eolian_Unit const* unit) @@ -545,7 +582,7 @@ struct function_def { attributes::regular_type_def const* typ = efl::eina::get(¶m.type.original_type); - if (typ && typ->is_function_ptr) + if (typ && typ->is_function_ptr()) { char typenam[2] = { 0, }; typenam[0] = template_typename++; @@ -568,7 +605,7 @@ struct function_def { attributes::regular_type_def const* typ = efl::eina::get(¶m.type.original_type); - if (typ && typ->is_function_ptr) + if (typ && typ->is_function_ptr()) { char typenam[2] = { 0, }; typenam[0] = template_typename++; @@ -652,8 +689,8 @@ struct event_def friend inline bool operator!=(event_def const& lhs, event_def const& rhs) { return !(lhs == rhs); - } - + } + event_def(type_def type, std::string name, std::string c_name, bool beta, bool protect) : type(type), name(name), c_name(c_name), beta(beta), protect(protect) {} event_def(Eolian_Event const* event, Eolian_Unit const* unit) @@ -835,7 +872,7 @@ struct klass_def Eolian_Class const* inherit = &*inherit_iterator; immediate_inherits.insert({inherit, {}}); } - std::function inherit_algo = + std::function inherit_algo = [&] (Eolian_Class const* inherit_klass) { for(efl::eina::iterator inherit_iterator ( ::eolian_class_inherits_get(inherit_klass)) @@ -1100,7 +1137,7 @@ template <> struct is_tuple : std::true_type {}; template <> struct is_tuple : std::true_type {}; - + } } } } diff --git a/src/lib/eolian_cxx/grammar/parameter.hpp b/src/lib/eolian_cxx/grammar/parameter.hpp index 68f5450dd1..e06cfeaaf0 100644 --- a/src/lib/eolian_cxx/grammar/parameter.hpp +++ b/src/lib/eolian_cxx/grammar/parameter.hpp @@ -28,7 +28,7 @@ struct parameter_type_generator attributes::regular_type_def const* typ = efl::eina::get(¶m.type.original_type); - if (typ && typ->is_function_ptr) + if (typ && typ->is_function_ptr()) return as_generator("F").generate(sink, attributes::unused, context); return as_generator diff --git a/src/tests/efl_mono/Structs.cs b/src/tests/efl_mono/Structs.cs new file mode 100644 index 0000000000..dcdea0d757 --- /dev/null +++ b/src/tests/efl_mono/Structs.cs @@ -0,0 +1,355 @@ +using System; +using System.Runtime.InteropServices; +using System.Linq; + +using static EinaTestData.BaseData; + +namespace TestSuite +{ + +class TestStructs +{ + // Auxiliary function // + + private static test.StructSimple structSimpleWithValues() + { + var simple = new test.StructSimple(); + + simple.Fbyte = (sbyte)-126; + simple.Fubyte = (byte) 254u; + simple.Fchar = '~'; + simple.Fshort = (short) -32766; + simple.Fushort = (ushort) 65534u; + simple.Fint = -32766; + simple.Fuint = 65534u; + simple.Flong = -2147483646; + simple.Fulong = 4294967294u; + simple.Fllong = -9223372036854775806; + simple.Fullong = 18446744073709551614u; + simple.Fint8 = (sbyte) -126; + simple.Fuint8 = (byte) 254u; + simple.Fint16 = (short) -32766; + simple.Fuint16 = (ushort) 65534u; + simple.Fint32 = -2147483646; + simple.Fuint32 = 4294967294u; + simple.Fint64 = -9223372036854775806; + simple.Fuint64 = 18446744073709551614u; + simple.Fssize = -2147483646; + simple.Fsize = 4294967294u; + simple.Fintptr = (IntPtr) 0xFE; + simple.Fptrdiff = -2147483646; + simple.Ffloat = -16777216.0f; + simple.Fdouble = -9007199254740992.0; + simple.Fbool = true; + simple.Fvoid_ptr = (IntPtr) 0xFE; + simple.Fenum = test.SampleEnum.V2; + simple.Fstring = "test/string"; + simple.Fmstring = "test/mstring"; + simple.Fstringshare = "test/stringshare"; + + return simple; + } + + private static void checkStructSimple(test.StructSimple simple) + { + Test.Assert(simple.Fbyte == (sbyte) -126); + Test.Assert(simple.Fubyte == (byte) 254u); + Test.Assert(simple.Fchar == '~'); + Test.Assert(simple.Fshort == (short) -32766); + Test.Assert(simple.Fushort == (ushort) 65534u); + Test.Assert(simple.Fint == -32766); + Test.Assert(simple.Fuint == 65534u); + Test.Assert(simple.Flong == -2147483646); + Test.Assert(simple.Fulong == 4294967294u); + Test.Assert(simple.Fllong == -9223372036854775806); + Test.Assert(simple.Fullong == 18446744073709551614u); + Test.Assert(simple.Fint8 == (sbyte) -126); + Test.Assert(simple.Fuint8 == (byte) 254u); + Test.Assert(simple.Fint16 == (short) -32766); + Test.Assert(simple.Fuint16 == (ushort) 65534u); + Test.Assert(simple.Fint32 == -2147483646); + Test.Assert(simple.Fuint32 == 4294967294u); + Test.Assert(simple.Fint64 == -9223372036854775806); + Test.Assert(simple.Fuint64 == 18446744073709551614u); + Test.Assert(simple.Fssize == -2147483646); + Test.Assert(simple.Fsize == 4294967294u); + Test.Assert(simple.Fintptr == (IntPtr) 0xFE); + Test.Assert(simple.Fptrdiff == -2147483646); + Test.Assert(simple.Ffloat == -16777216.0f); + Test.Assert(simple.Fdouble == -9007199254740992.0); + Test.Assert(simple.Fbool == true); + Test.Assert(simple.Fvoid_ptr == (IntPtr) 0xFE); + Test.Assert(simple.Fenum == test.SampleEnum.V2); + Test.Assert(simple.Fstring == "test/string"); + Test.Assert(simple.Fmstring == "test/mstring"); + Test.Assert(simple.Fstringshare == "test/stringshare"); + } + + private static void checkZeroedStructSimple(test.StructSimple simple) + { + Test.Assert(simple.Fbyte == 0); + Test.Assert(simple.Fubyte == 0); + Test.Assert(simple.Fchar == '\0'); + Test.Assert(simple.Fshort == 0); + Test.Assert(simple.Fushort == 0); + Test.Assert(simple.Fint == 0); + Test.Assert(simple.Fuint == 0); + Test.Assert(simple.Flong == 0); + Test.Assert(simple.Fulong == 0); + Test.Assert(simple.Fllong == 0); + Test.Assert(simple.Fullong == 0); + Test.Assert(simple.Fint8 == 0); + Test.Assert(simple.Fuint8 == 0); + Test.Assert(simple.Fint16 == 0); + Test.Assert(simple.Fuint16 == 0); + Test.Assert(simple.Fint32 == 0); + Test.Assert(simple.Fuint32 == 0); + Test.Assert(simple.Fint64 == 0); + Test.Assert(simple.Fuint64 == 0); + Test.Assert(simple.Fssize == 0); + Test.Assert(simple.Fsize == 0); + Test.Assert(simple.Fintptr == IntPtr.Zero); + Test.Assert(simple.Fptrdiff == 0); + Test.Assert(simple.Ffloat == 0); + Test.Assert(simple.Fdouble == 0); + Test.Assert(simple.Fbool == false); + Test.Assert(simple.Fvoid_ptr == IntPtr.Zero); + Test.Assert(simple.Fenum == test.SampleEnum.V0); + Test.Assert(simple.Fstring == null); + Test.Assert(simple.Fmstring == null); + Test.Assert(simple.Fstringshare == null); + } + + private static test.StructComplex structComplexWithValues() + { + var complex = new test.StructComplex(); + + complex.Farray = new eina.Array(); + complex.Farray.Push(0x0); + complex.Farray.Push(0x2A); + complex.Farray.Push(0x42); + + complex.Finarray = new eina.Inarray(); + complex.Finarray.Push(0x0); + complex.Finarray.Push(0x2A); + complex.Finarray.Push(0x42); + + + complex.Flist = new eina.List(); + complex.Flist.Append("0x0"); + complex.Flist.Append("0x2A"); + complex.Flist.Append("0x42"); + + complex.Finlist = new eina.Inlist(); + complex.Finlist.Append(0x0); + complex.Finlist.Append(0x2A); + complex.Finlist.Append(0x42); + + complex.Fhash = new eina.Hash(); + complex.Fhash["aa"] = "aaa"; + complex.Fhash["bb"] = "bbb"; + complex.Fhash["cc"] = "ccc"; + + complex.Fiterator = complex.Farray.GetIterator(); + + complex.Fany_value = new eina.Value(eina.ValueType.Double); + complex.Fany_value.Set(-9007199254740992.0); + + complex.Fany_value_ptr = new eina.Value(eina.ValueType.String); + complex.Fany_value_ptr.Set("abc"); + + complex.Fbinbuf = new eina.Binbuf(); + complex.Fbinbuf.Append(126); + + complex.Fslice.Length = 1; + complex.Fslice.Mem = eina.MemoryNative.Alloc(1); + Marshal.WriteByte(complex.Fslice.Mem, 125); + + complex.Fobj = new test.NumberwrapperConcrete(); + complex.Fobj.SetNumber(42); + + return complex; + } + + private static void checkStructComplex(test.StructComplex complex) + { + Test.Assert(complex.Farray.ToArray().SequenceEqual(base_seq_int)); + + Test.Assert(complex.Finarray.ToArray().SequenceEqual(base_seq_int)); + + Test.Assert(complex.Flist.ToArray().SequenceEqual(base_seq_str)); + + Test.Assert(complex.Finlist.ToArray().SequenceEqual(base_seq_int)); + + Test.Assert(complex.Fhash["aa"] == "aaa"); + Test.Assert(complex.Fhash["bb"] == "bbb"); + Test.Assert(complex.Fhash["cc"] == "ccc"); + + int idx = 0; + foreach (int e in complex.Fiterator) + { + Test.Assert(e == base_seq_int[idx]); + ++idx; + } + + double double_val = 0; + Test.Assert(complex.Fany_value.Get(out double_val)); + Test.Assert(double_val == -9007199254740992.0); + + string str_val = null; + Test.Assert(complex.Fany_value_ptr.Get(out str_val)); + Test.Assert(str_val == "abc"); + + Test.Assert(complex.Fbinbuf.Length == 1); + Test.Assert(complex.Fbinbuf.GetBytes()[0] == 126); + + Test.Assert(complex.Fslice.Length == 1); + Test.Assert(complex.Fslice.GetBytes()[0] == 125); + + Test.Assert(complex.Fobj != null); + Test.Assert(complex.Fobj.GetNumber() == 42); + } + + + private static void checkZeroedStructComplex(test.StructComplex complex) + { + Test.Assert(complex.Farray == null); + Test.Assert(complex.Finarray == null); + Test.Assert(complex.Flist == null); + Test.Assert(complex.Finlist == null); + Test.Assert(complex.Fhash == null); + Test.Assert(complex.Fiterator == null); + Test.Assert(complex.Fany_value == null); + Test.Assert(complex.Fany_value_ptr == null); + Test.Assert(complex.Fbinbuf == null); + + Test.Assert(complex.Fslice.Length == 0); + Test.Assert(complex.Fslice.Mem == IntPtr.Zero); + + Test.Assert(complex.Fobj == null); + } + + // Test cases // + + // Default initialization (C# side) + + private static void simple_default_instantiation() + { + var simple = new test.StructSimple(); + checkZeroedStructSimple(simple); + } + + private static void complex_default_instantiation() + { + var complex = new test.StructComplex(); + checkZeroedStructComplex(complex); + } + + // As parameters + + public static void simple_in() + { + var simple = structSimpleWithValues(); + test.Testing t = new test.TestingConcrete(); + bool r = t.StructSimpleIn(simple); + Test.Assert(r, "Function returned false"); + } + + // public static void simple_ptr_in() + // { + // var simple = structSimpleWithValues(); + // test.Testing t = new test.TestingConcrete(); + // bool r = t.struct_simple_ptr_in(simple); + // Test.Assert(r, "Function returned false"); + // } + + // public static void simple_ptr_in_own() + // { + // var simple = structSimpleWithValues(); + // test.Testing t = new test.TestingConcrete(); + // bool r = t.struct_simple_ptr_in_own(simple); + // Test.Assert(r, "Function returned false"); + // } + + public static void simple_out() + { + var simple = new test.StructSimple(); + test.Testing t = new test.TestingConcrete(); + bool r = t.StructSimpleOut(ref simple); + Test.Assert(r, "Function returned false"); + checkStructSimple(simple); + } + + // public static void simple_ptr_out() + // { + // } + + // public static void simple_ptr_out_own() + // { + // } + + public static void simple_return() + { + test.Testing t = new test.TestingConcrete(); + var simple = t.StructSimpleReturn(); + checkStructSimple(simple); + } + + // public static void simple_ptr_return() + // { + // } + + // public static void simple_ptr_return_own() + // { + // } + + public static void complex_in() + { + var complex = structComplexWithValues(); + test.Testing t = new test.TestingConcrete(); + bool r = t.StructComplexIn(complex); + Test.Assert(r, "Function returned false"); + } + + // public static void complex_ptr_in() + // { + // } + + // public static void complex_ptr_in_own() + // { + // } + + public static void complex_out() + { + var complex = new test.StructComplex(); + test.Testing t = new test.TestingConcrete(); + bool r = t.StructComplexOut(ref complex); + Test.Assert(r, "Function returned false"); + checkStructComplex(complex); + } + + // public static void complex_ptr_out() + // { + // } + + // public static void complex_ptr_out_own() + // { + // } + + public static void complex_return() + { + test.Testing t = new test.TestingConcrete(); + var complex = t.StructComplexReturn(); + checkStructComplex(complex); + } + + // public static void complex_ptr_return() + // { + // } + + // public static void complex_ptr_return_own() + // { + // } +} + +} diff --git a/src/tests/efl_mono/libefl_mono_native_test.c b/src/tests/efl_mono/libefl_mono_native_test.c index 0b73d7e76b..b8cc8d58e4 100644 --- a/src/tests/efl_mono/libefl_mono_native_test.c +++ b/src/tests/efl_mono/libefl_mono_native_test.c @@ -34,6 +34,9 @@ #include "test_numberwrapper.eo.h" #include "test_testing.eo.h" +#define EQUAL(a, b) ((a) == (b) ? 1 : (fprintf(stderr, "NOT EQUAL! %s:%i (%s)", __FILE__, __LINE__, __FUNCTION__), fflush(stderr), 0)) +#define STR_EQUAL(a, b) (strcmp((a), (b)) == 0 ? 1 : (fprintf(stderr, "NOT EQUAL! %s:%i (%s) '%s' != '%s'", __FILE__, __LINE__, __FUNCTION__, (a), (b)), fflush(stderr), 0)) + typedef struct Test_Testing_Data { Test_SimpleCb cb; @@ -3123,6 +3126,397 @@ Eina_Error _test_testing_returns_error(EINA_UNUSED Eo *obj, Test_Testing_Data *p return pd->error_code; } +// // +// Structs // +// // + +// auxiliary functions + +static +void struct_simple_with_values(Test_StructSimple *simple) +{ + simple->fbyte = -126; + simple->fubyte = 254u; + simple->fchar = '~'; + simple->fshort = -32766; + simple->fushort = 65534u; + simple->fint = -32766; + simple->fuint = 65534u; + simple->flong = -2147483646; + simple->fulong = 4294967294u; + simple->fllong = -9223372036854775806; + simple->fullong = 18446744073709551614u; + simple->fint8 = -126; + simple->fuint8 = 254u; + simple->fint16 = -32766; + simple->fuint16 = 65534u; + simple->fint32 = -2147483646; + simple->fuint32 = 4294967294u; + simple->fint64 = -9223372036854775806; + simple->fuint64 = 18446744073709551614u; + simple->fssize = -2147483646; + simple->fsize = 4294967294u; + simple->fintptr = 0xFE; + simple->fptrdiff = -2147483646; + simple->ffloat = -16777216.0; + simple->fdouble = -9007199254740992.0; + simple->fbool = EINA_TRUE; + simple->fvoid_ptr = (void*) 0xFE; + simple->fenum = TEST_SAMPLEENUM_V2; + simple->fstring = "test/string"; + simple->fmstring = strdup("test/mstring"); + simple->fstringshare = eina_stringshare_add("test/stringshare"); +} + +static +Eina_Bool check_and_modify_struct_simple(Test_StructSimple *simple) +{ + Eina_Bool ret = + EQUAL(simple->fbyte, -126) + && EQUAL(simple->fubyte, 254u) + && EQUAL(simple->fchar, '~') + && EQUAL(simple->fshort, -32766) + && EQUAL(simple->fushort, 65534u) + && EQUAL(simple->fint, -32766) + && EQUAL(simple->fuint, 65534u) + && EQUAL(simple->flong, -2147483646) + && EQUAL(simple->fulong, 4294967294u) + && EQUAL(simple->fllong, -9223372036854775806) + && EQUAL(simple->fullong, 18446744073709551614u) + && EQUAL(simple->fint8, -126) + && EQUAL(simple->fuint8, 254u) + && EQUAL(simple->fint16, -32766) + && EQUAL(simple->fuint16, 65534u) + && EQUAL(simple->fint32, -2147483646) + && EQUAL(simple->fuint32, 4294967294u) + && EQUAL(simple->fint64, -9223372036854775806) + && EQUAL(simple->fuint64, 18446744073709551614u) + && EQUAL(simple->fssize, -2147483646) + && EQUAL(simple->fsize, 4294967294u) + && EQUAL(simple->fintptr, 0xFE) + && EQUAL(simple->fptrdiff, -2147483646) + && EQUAL(simple->ffloat, -16777216.0) + && EQUAL(simple->fdouble, -9007199254740992.0) + && EQUAL(simple->fbool, EINA_TRUE) + && EQUAL(simple->fvoid_ptr, (void*) 0xFE) + && EQUAL(simple->fenum, TEST_SAMPLEENUM_V2) + && STR_EQUAL(simple->fstring, "test/string") + && STR_EQUAL(simple->fmstring, "test/mstring") + && STR_EQUAL(simple->fstringshare, "test/stringshare") + ; + + if (!ret) + return ret; + + simple->fmstring[4] = '-'; + return strcmp(simple->fmstring, "test-mstring") == 0; +} + +static +Eina_Bool check_zeroed_struct_simple(Test_StructSimple *simple) +{ + Eina_Bool ret = + simple->fbyte == 0 + && simple->fubyte == 0 + && simple->fchar == '\0' + && simple->fshort == 0 + && simple->fushort == 0 + && simple->fint == 0 + && simple->fuint == 0 + && simple->flong == 0 + && simple->fulong == 0 + && simple->fllong == 0 + && simple->fullong == 0 + && simple->fint8 == 0 + && simple->fuint8 == 0 + && simple->fint16 == 0 + && simple->fuint16 == 0 + && simple->fint32 == 0 + && simple->fuint32 == 0 + && simple->fint64 == 0 + && simple->fuint64 == 0 + && simple->fssize == 0 + && simple->fsize == 0 + && simple->fintptr == 0x00 + && simple->fptrdiff == 0 + && simple->ffloat == 0 + && simple->fdouble == 0 + && simple->fbool == EINA_FALSE + && simple->fvoid_ptr == NULL + && simple->fenum == TEST_SAMPLEENUM_V0 + && simple->fstring == NULL + && simple->fmstring == NULL + && simple->fstringshare == NULL + ; + + return ret; +} + +static +void struct_complex_with_values(Test_StructComplex *complex) +{ + complex->farray = eina_array_new(4); + eina_array_push(complex->farray, _new_int(0x0)); + eina_array_push(complex->farray, _new_int(0x2A)); + eina_array_push(complex->farray, _new_int(0x42)); + + complex->finarray = eina_inarray_new(sizeof(int), 0); + eina_inarray_push(complex->finarray, _int_ref(0x0)); + eina_inarray_push(complex->finarray, _int_ref(0x2A)); + eina_inarray_push(complex->finarray, _int_ref(0x42)); + + complex->flist = eina_list_append(complex->flist, strdup("0x0")); + complex->flist = eina_list_append(complex->flist, strdup("0x2A")); + complex->flist = eina_list_append(complex->flist, strdup("0x42")); + + complex->finlist = eina_inlist_append(complex->finlist, _new_inlist_int(0x0)); + complex->finlist = eina_inlist_append(complex->finlist, _new_inlist_int(0x2A)); + complex->finlist = eina_inlist_append(complex->finlist, _new_inlist_int(0x42)); + + complex->fhash = eina_hash_string_superfast_new(NULL); + eina_hash_add(complex->fhash, "aa", strdup("aaa")); + eina_hash_add(complex->fhash, "bb", strdup("bbb")); + eina_hash_add(complex->fhash, "cc", strdup("ccc")); + + complex->fiterator = eina_array_iterator_new(complex->farray); + + eina_value_setup(&complex->fany_value, EINA_VALUE_TYPE_DOUBLE); + eina_value_set(&complex->fany_value, -9007199254740992.0); + + complex->fany_value_ptr = eina_value_new(EINA_VALUE_TYPE_STRING); + eina_value_set(complex->fany_value_ptr, "abc"); + + complex->fbinbuf = eina_binbuf_new(); + eina_binbuf_append_char(complex->fbinbuf, 126); + + complex->fslice.len = 1; + complex->fslice.mem = malloc(1); + memset((void*)complex->fslice.mem, 125, 1); + + complex->fobj = _new_obj(42); +} + +static +Eina_Bool check_and_modify_struct_complex(Test_StructComplex *complex) +{ + if (!_array_int_equal(complex->farray, base_seq_int, base_seq_int_size)) + return EINA_FALSE; + + if (!_inarray_int_equal(complex->finarray, base_seq_int, base_seq_int_size)) + return EINA_FALSE; + + if (!_list_str_equal(complex->flist, base_seq_str, base_seq_str_size)) + return EINA_FALSE; + + if (!_inlist_int_equal(complex->finlist, base_seq_int, base_seq_int_size)) + return EINA_FALSE; + + if (!_hash_str_check(complex->fhash, "aa", "aaa") + || !_hash_str_check(complex->fhash, "bb", "bbb") + || !_hash_str_check(complex->fhash, "cc", "ccc")) + return EINA_FALSE; + + if (!_iterator_int_equal(complex->fiterator, base_seq_int, base_seq_int_size, EINA_FALSE)) + return EINA_FALSE; + + double double_val = 0; + if (!eina_value_get(&complex->fany_value, &double_val) || double_val != -9007199254740992.0) + return EINA_FALSE; + + const char *str_val = NULL; + if (!eina_value_get(complex->fany_value_ptr, &str_val) || strcmp(str_val, "abc") != 0) + return EINA_FALSE; + + if (eina_binbuf_length_get(complex->fbinbuf) != 1 || eina_binbuf_string_get(complex->fbinbuf)[0] != 126) + return EINA_FALSE; + + if (complex->fslice.len != 1 || *(char*)complex->fslice.mem != 125) + return EINA_FALSE; + + if (complex->fobj == NULL || test_numberwrapper_number_get(complex->fobj) != 42) + return EINA_FALSE; + + return EINA_TRUE; +} + +static +Eina_Bool check_zeroed_struct_complex(Test_StructComplex *complex) +{ + Eina_Bool ret = + complex->farray == NULL + && complex->finarray == NULL + && complex->flist == NULL + && complex->finlist == NULL + && complex->fhash == NULL + && complex->fiterator == NULL + + && complex->fany_value.type == NULL + && complex->fany_value.value._guarantee == 0 + + && complex->fany_value_ptr == NULL + && complex->fbinbuf == NULL + + && complex->fslice.len == 0 + && complex->fslice.mem == NULL + + && complex->fobj == NULL + ; + + return ret; +} + +// with simple types + +EOLIAN +Eina_Bool _test_testing_struct_simple_in(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple simple) +{ + return check_and_modify_struct_simple(&simple); +} + +EOLIAN +Eina_Bool _test_testing_struct_simple_ptr_in(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple *simple) +{ + (void) simple; + EINA_LOG_ERR("Not implemented!"); + return EINA_FALSE; +} + +EOLIAN +Eina_Bool _test_testing_struct_simple_ptr_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple *simple) +{ + (void) simple; + EINA_LOG_ERR("Not implemented!"); + return EINA_FALSE; +} + +EOLIAN +Eina_Bool _test_testing_struct_simple_out(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple *simple) +{ + if (!simple) + { + EINA_LOG_ERR("Null struct pointer"); + return EINA_FALSE; + } + + struct_simple_with_values(simple); + + return EINA_TRUE; +} + +EOLIAN +Eina_Bool _test_testing_struct_simple_ptr_out(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple **simple) +{ + (void) simple; + EINA_LOG_ERR("Not implemented!"); + return EINA_FALSE; +} + +EOLIAN +Eina_Bool _test_testing_struct_simple_ptr_out_own(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructSimple **simple) +{ + (void) simple; + EINA_LOG_ERR("Not implemented!"); + return EINA_FALSE; +} + +EOLIAN +Test_StructSimple _test_testing_struct_simple_return(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd) +{ + Test_StructSimple simple = {0,}; + struct_simple_with_values(&simple); + return simple; +} + +EOLIAN +Test_StructSimple *_test_testing_struct_simple_ptr_return(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd) +{ + EINA_LOG_ERR("Not implemented!"); + return NULL; +} + +EOLIAN +Test_StructSimple *_test_testing_struct_simple_ptr_return_own(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd) +{ + EINA_LOG_ERR("Not implemented!"); + return NULL; +} + +// with complex types + +EOLIAN +Eina_Bool _test_testing_struct_complex_in(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructComplex complex) +{ + return check_and_modify_struct_complex(&complex); +} + +EOLIAN +Eina_Bool _test_testing_struct_complex_ptr_in(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructComplex *complex) +{ + (void) complex; + EINA_LOG_ERR("Not implemented!"); + return EINA_FALSE; +} + +EOLIAN +Eina_Bool _test_testing_struct_complex_ptr_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructComplex *complex) +{ + (void) complex; + EINA_LOG_ERR("Not implemented!"); + return EINA_FALSE; +} + +EOLIAN +Eina_Bool _test_testing_struct_complex_out(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructComplex *complex) +{ + if (!complex) + { + EINA_LOG_ERR("Null struct pointer"); + return EINA_FALSE; + } + + struct_complex_with_values(complex); + + return EINA_TRUE; +} + +EOLIAN +Eina_Bool _test_testing_struct_complex_ptr_out(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructComplex **complex) +{ + (void) complex; + EINA_LOG_ERR("Not implemented!"); + return EINA_FALSE; +} + +EOLIAN +Eina_Bool _test_testing_struct_complex_ptr_out_own(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Test_StructComplex **complex) +{ + (void) complex; + EINA_LOG_ERR("Not implemented!"); + return EINA_FALSE; +} + +EOLIAN +Test_StructComplex _test_testing_struct_complex_return(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd) +{ + Test_StructComplex complex = {0,}; + struct_complex_with_values(&complex); + return complex; +} + +EOLIAN +Test_StructComplex* _test_testing_struct_complex_ptr_return(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd) +{ + EINA_LOG_ERR("Not implemented!"); + return NULL; +} + +EOLIAN +Test_StructComplex* _test_testing_struct_complex_ptr_return_own(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd) +{ + EINA_LOG_ERR("Not implemented!"); + return NULL; +} + // // // Class constructor // // diff --git a/src/tests/efl_mono/test_testing.eo b/src/tests/efl_mono/test_testing.eo index bf13a57283..7d7ab51275 100644 --- a/src/tests/efl_mono/test_testing.eo +++ b/src/tests/efl_mono/test_testing.eo @@ -1,5 +1,79 @@ import eina_types; +enum Test.SampleEnum { + v0, + v1, + v2, + v3, + v4, +} + +struct Test.StructSimple +{ + fbyte: byte; + fubyte: ubyte; + fchar: char; + fshort: short; + fushort: ushort; + fint: int; + fuint: uint; + flong: long; + fulong: ulong; + fllong: llong; + fullong: ullong; + fint8: int8; + fuint8: uint8; + fint16: int16; + fuint16: uint16; + fint32: int32; + fuint32: uint32; + fint64: int64; + fuint64: uint64; + fssize: ssize; + fsize: size; + fintptr: intptr; + // fuintptr: uintptr; // TODO + fptrdiff: ptrdiff; + ffloat: float; + fdouble: double; + fbool: bool; + fvoid_ptr: void_ptr; + fenum: Test.SampleEnum; + // fboolptr: ptr(bool); // TODO + // fbyteptr: ptr(byte); + // fubyteptr: ptr(ubyte); + // fcharptr: ptr(char); + // fuint8ptr: ptr(uint8); + // fint16ptr: ptr(int16); + // fuint64ptr: ptr(uint64); + // fssizeptr: ptr(ssize); + // fsizeptr: ptr(size); + // fintptrptr: ptr(intptr); + // fptrdiffptr: ptr(ptrdiff); + // ffloatptr: ptr(float); + // fdoubleptr: ptr(double); + // fvoid_ptrptr: ptr(void_ptr); + // fenumptr: ptr(Test.SampleEnum); + fstring: string; + fmstring: mstring; + fstringshare: stringshare; +} + +struct Test.StructComplex { + farray: array; + finarray: inarray; + flist: list; + finlist: inlist; + fhash: hash; + fiterator: iterator; + fany_value: any_value; + fany_value_ptr: any_value_ptr; + fbinbuf: ptr(Eina.Binbuf); + fslice: Eina.Slice; + // fslice: ptr(Eina.Slice); // TODO + fobj: Test.Numberwrapper; +} + function Test.SimpleCb { params { a: int; @@ -1238,6 +1312,116 @@ class Test.Testing (Efl.Object) { @out value: any_value; } } + + /* Structs */ + + struct_simple_in { + params { + @in simple: Test.StructSimple; + } + return: bool; + } + + // struct_simple_ptr_in { + // params { + // @in simple: ptr(Test.StructSimple); + // } + // return: bool; + // } + // + // struct_simple_ptr_in_own { + // params { + // @in simple: ptr(Test.StructSimple) @owned; + // } + // return: bool; + // } + + struct_simple_out { + params { + @out simple: Test.StructSimple; + } + return: bool; + } + + // struct_simple_ptr_out { + // params { + // @out simple: ptr(Test.StructSimple); + // } + // return: bool; + // } + // + // struct_simple_ptr_out_own { + // params { + // @out simple: ptr(Test.StructSimple) @owned; + // } + // return: bool; + // } + + struct_simple_return { + return: Test.StructSimple; + } + + // struct_simple_ptr_return { + // return: ptr(Test.StructSimple); + // } + // + // struct_simple_ptr_return_own { + // return: ptr(Test.StructSimple) @owned; + // } + + struct_complex_in { + params { + @in complex: Test.StructComplex; + } + return: bool; + } + + // struct_complex_ptr_in { + // params { + // @in complex: ptr(Test.StructComplex); + // } + // return: bool; + // } + // + // struct_complex_ptr_in_own { + // params { + // @in complex: ptr(Test.StructComplex) @owned; + // } + // return: bool; + // } + + struct_complex_out { + params { + @out complex: Test.StructComplex; + } + return: bool; + } + + // struct_complex_ptr_out { + // params { + // @out complex: ptr(Test.StructComplex); + // } + // return: bool; + // } + // + // struct_complex_ptr_out_own { + // params { + // @out complex: ptr(Test.StructComplex) @owned; + // } + // return: bool; + // } + + struct_complex_return { + return: Test.StructComplex; + } + + // struct_complex_ptr_return { + // return: ptr(Test.StructComplex); + // } + // + // struct_complex_ptr_return_own { + // return: ptr(Test.StructComplex) @owned; + // } } implements { class.constructor;