summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitor Sousa <vitorsousasilva@gmail.com>2017-12-12 12:06:46 -0200
committerVitor Sousa <vitorsousasilva@gmail.com>2017-12-15 22:26:29 -0200
commitacd99be98bc6f3218af9322b23acb52ed29fb008 (patch)
tree3cee18189cc4ab31f4595721ca904bf0cc8d6847
parentb20dd869a4a10fb28a9c743910e2f2a1d2e7d1cc (diff)
downloadefl-acd99be98bc6f3218af9322b23acb52ed29fb008.tar.gz
efl_mono: tests and better support for structs, plus some other fixes
Fix several integer binding type deduction based in its size on C. Generation for function pointers no longer use modified argument name which is different from the parameter name. New generation context for structs. bool from UnmanagedType.I1 to UnmanagedType.U1 (correct use inside structs according to mono documentation). byte (signed char) and int8 now is correctly represented by sbyte in C#. Check parameter direction in some out generators in parameter.hh. Add efl_libs.csv to gitignore. Make eina.Value pointer constructor public. Add missing fields to efl.kw_event.Description struct. Remove eina.File workaround (let struct gen handle it). Remove is_function_ptr bool from regular_type_def and add a typedecl_type enum to it. Also add some helper methods for easier comparison. Left some test cases commented for when pointer parameters are properly working.
-rw-r--r--src/Makefile_Efl_Mono.am1
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_pointer.hh4
-rw-r--r--src/bin/eolian_mono/eolian/mono/generation_contexts.hh1
-rw-r--r--src/bin/eolian_mono/eolian/mono/helpers.hh59
-rw-r--r--src/bin/eolian_mono/eolian/mono/marshall_annotation.hh8
-rw-r--r--src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh8
-rw-r--r--src/bin/eolian_mono/eolian/mono/parameter.hh114
-rw-r--r--src/bin/eolian_mono/eolian/mono/struct_definition.hh437
-rw-r--r--src/bin/eolian_mono/eolian/mono/type_impl.hh39
-rw-r--r--src/bin/eolian_mono/eolian_mono.cc3
-rw-r--r--src/bindings/mono/efl_mono/.gitignore1
-rw-r--r--src/bindings/mono/eina_mono/eina_value.cs2
-rw-r--r--src/bindings/mono/eo_mono/workaround.cs17
-rw-r--r--src/lib/eolian_cxx/grammar/converting_argument.hpp2
-rw-r--r--src/lib/eolian_cxx/grammar/klass_def.hpp89
-rw-r--r--src/lib/eolian_cxx/grammar/parameter.hpp2
-rw-r--r--src/tests/efl_mono/Structs.cs355
-rw-r--r--src/tests/efl_mono/libefl_mono_native_test.c394
-rw-r--r--src/tests/efl_mono/test_testing.eo184
19 files changed, 1618 insertions, 102 deletions
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<bool> 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<bool> 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 &param, 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<attributes::regular_type_def>(&param.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<attributes::regular_type_def>(&param.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<attributes::regular_type_def>(&param.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<typename T>
@@ -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 <typename OutputIterator, typename Context>
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<attributes::regular_type_def>(&param.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<attributes::regular_type_def>(&param.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 <typename OutputIterator, typename Context>
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<attributes::regular_type_def>(&param.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 <typename OutputIterator, typename Context>
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<attributes::regular_type_def>(&param.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 <typename OutputIterator, typename Context>
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<attributes::regular_type_def>(&param.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 <typename OutputIterator, typename Context>
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<attributes::regular_type_def>(&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 <typename OutputIterator, typename Context>
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<attributes::regular_type_def>(&param.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 <typename OutputIterator, typename Context>
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<attributes::regular_type_def>(&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;
-
- for (auto it=struct_.namespaces.begin(); it != struct_.namespaces.end(); it++)
- {
- full_name += *it + ".";
- }
-
- 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";
+ return struct_.cxx_name;
+}
+
+inline std::string binding_struct_internal_name(attributes::struct_def const& struct_)
+{
+ return struct_.cxx_name + "_StructInternal";
+}
+
+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 <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const
{
- if (is_struct_blacklisted(struct_))
- return true;
-
- std::vector<std::string> 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 <typename OutputIterator, typename Context>
+ 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<attributes::klass_name>(&field.type.original_type);
+ auto regular = efl::eina::get<attributes::regular_type_def>(&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 <typename OutputIterator, typename Context>
+ 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<attributes::regular_type_def>(&field.type.original_type);
+ auto klass = efl::eina::get<attributes::klass_name>(&field.type.original_type);
+ auto complex = efl::eina::get<attributes::complex_type_def>(&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 <typename OutputIterator, typename Context>
+ 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<attributes::regular_type_def>(&field.type.original_type);
+ auto klass = efl::eina::get<attributes::klass_name>(&field.type.original_type);
+ auto complex = efl::eina::get<attributes::complex_type_def>(&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 <typename OutputIterator, typename Context>
+ 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 <typename OutputIterator, typename Context>
+ bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const
+ {
+ if (is_struct_blacklisted(struct_))
+ return true;
+
+ std::vector<std::string> 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<int, 1> {};
+
+template <>
+struct attributes_needed< ::eolian_mono::struct_internal_definition_generator> : std::integral_constant<int, 1> {};
+
+template <>
+struct attributes_needed< ::eolian_mono::to_internal_field_convert_generator> : std::integral_constant<int, 1> {};
+
+template <>
+struct attributes_needed< ::eolian_mono::to_external_field_convert_generator> : std::integral_constant<int, 1> {};
+
+template <>
+struct attributes_needed< ::eolian_mono::struct_binding_conversion_functions_generator> : std::integral_constant<int, 1> {};
+
+template <>
+struct attributes_needed< ::eolian_mono::struct_entities_generator> : std::integral_constant<int, 1> {};
}
} } }
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 <typename T>
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 <typename T>
+attributes::regular_type_def replace_base_integer(attributes::regular_type_def v)
+{
+ bool s = std::is_signed<T>::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<short>(regular); }}
+ , {"int", nullptr, [&] { return replace_base_integer<int>(regular); }}
+ , {"long", nullptr, [&] { return replace_base_integer<long>(regular); }}
+ , {"llong", nullptr, [&] { return replace_base_integer<long long>(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<ssize_t>(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<unsigned short>(regular); }}
+ , {"uint", nullptr, [&] { return replace_base_integer<unsigned int>(regular); }}
+ , {"ulong", nullptr, [&] { return replace_base_integer<unsigned long>(regular); }}
+ , {"ullong", nullptr, [&] { return replace_base_integer<unsigned long long>(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<size_t>(regular); }}
- , {"ptrdiff", nullptr, [&] { return replace_base_type(regular, " long"); }}
+ , {"ptrdiff", nullptr, [&] { return replace_base_integer<ptrdiff_t>(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<Value>, IEquatable<Value>
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<string, IntPtr> descriptions = new Dictionary<string, IntPtr>();
@@ -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 <typename OutputIterator, typename Context>
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<T, U> 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<std::string> namespaces;
@@ -168,19 +196,28 @@ get(klass_name const& klass)
{
return tuple_element<N, klass_name>::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<std::string> 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<std::string> 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<const char> 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<attributes::regular_type_def>(&param.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<attributes::regular_type_def>(&param.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<void(Eolian_Class const*)> inherit_algo =
+ std::function<void(Eolian_Class const*)> inherit_algo =
[&] (Eolian_Class const* inherit_klass)
{
for(efl::eina::iterator<Eolian_Class const> inherit_iterator ( ::eolian_class_inherits_get(inherit_klass))
@@ -1100,7 +1137,7 @@ template <>
struct is_tuple<attributes::parameter_def> : std::true_type {};
template <>
struct is_tuple<attributes::event_def> : 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<attributes::regular_type_def>(&param.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<int>();
+ complex.Farray.Push(0x0);
+ complex.Farray.Push(0x2A);
+ complex.Farray.Push(0x42);
+
+ complex.Finarray = new eina.Inarray<int>();
+ complex.Finarray.Push(0x0);
+ complex.Finarray.Push(0x2A);
+ complex.Finarray.Push(0x42);
+
+
+ complex.Flist = new eina.List<string>();
+ complex.Flist.Append("0x0");
+ complex.Flist.Append("0x2A");
+ complex.Flist.Append("0x42");
+
+ complex.Finlist = new eina.Inlist<int>();
+ complex.Finlist.Append(0x0);
+ complex.Finlist.Append(0x2A);
+ complex.Finlist.Append(0x42);
+
+ complex.Fhash = new eina.Hash<string, string>();
+ 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<ptr(int)>;
+ finarray: inarray<int>;
+ flist: list<string>;
+ finlist: inlist<ptr(int)>;
+ fhash: hash<string, string>;
+ fiterator: iterator<ptr(int)>;
+ 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;