efl-mono: Add support for dotnet core

Summary:
This commits adds dotnet as a supported C# platform for EFL# bindings.

Due to differences between Mono and Dotnet regarding DllImport, the
bindings now are using an imperative approach to load the function
pointers through the NativeModule and FunctionWrapper classes. These
classes handle the dlopen/LoadLibrary and dlsym/GetProcAddress calls.

Also, the previous caching of non-owned strings returned to native code
was removed until further memory checks.

We also had to create workaround for bool and chars in Structs for C#
marshaling. Going through System.Byte instead and Marshaling manually
to their respective types.

In order to actually build efl_mono.dll with dotnet right now,
issue #4782 from Meson should be fixed to make it properly detect and
used the Dotnet compiler. Also use "-Ddotnet=true" when running meson.

Fixes T7394

Reviewers: felipealmeida, vitor.sousa, bu5hm4n

Reviewed By: vitor.sousa

Subscribers: cedric

Tags: #efl

Maniphest Tasks: T7394

Differential Revision: https://phab.enlightenment.org/D8069
This commit is contained in:
Felipe Magno de Almeida 2019-01-16 16:29:56 +09:00 committed by Vitor Sousa
parent dd89eb2fd1
commit f392c5a436
36 changed files with 1028 additions and 472 deletions

View File

@ -4,8 +4,25 @@ efl_custom_exports_mono_files = \
efl_eo_mono_files = \
bindings/mono/eo_mono/iwrapper.cs \
bindings/mono/eo_mono/FunctionWrapper.cs \
bindings/mono/eo_mono/NativeModule.cs \
bindings/mono/eo_mono/workaround.cs
if HAVE_WIN32
efl_eo_mono_files += \
bindings/mono/eo_mono/FunctionWrapper_Windows.cs \
bindings/mono/eo_mono/NativeModule_Windows.cs
else
efl_eo_mono_files += \
bindings/mono/eo_mono/FunctionWrapper_Unix.cs \
bindings/mono/eo_mono/NativeModule_Unix.cs
endif
efl_eina_mono_files = \
bindings/mono/eina_mono/eina_config.cs \
bindings/mono/eina_mono/eina_array.cs \
@ -293,7 +310,7 @@ msbuildcsprojs: ../libefl_mono.csproj
done
### Some hard-coded runtime dependencies for tests and examples
TEST_PATHS = $(abs_top_builddir)/src/lib/efl_mono:$(abs_top_builddir)/src/lib/efl_mono/.libs:$(abs_top_builddir)/src/lib/eina/.libs:$(abs_top_builddir)/src/lib/ecore/.libs:$(abs_top_builddir)/src/lib/ecore_evas/.libs:$(abs_top_builddir)/src/lib/eo/.libs:$(abs_top_builddir)/src/lib/evas/.libs:$(abs_top_builddir)/src/lib/emile/.libs:$(abs_top_builddir)/src/lib/eet/.libs:$(abs_top_builddir)/src/lib/efl/.libs:$(abs_top_builddir)/src/ecore-file/.libs:$(abs_top_builddir)/src/lib/efl-input/.libs:$(abs_top_builddir)/src/lib/edje/.libs:$(abs_top_builddir)/src/lib/ethumb/.libs:$(abs_top_builddir)/src/lib/ethumb-client/.libs:$(abs_top_builddir)/src/lib/emotion/.libs:$(abs_top_builddir)/src/lib/ecore-imf/.libs:$(abs_top_builddir)/src/lib/ecore-con/.libs:$(abs_top_builddir)/src/lib/eldbus/.libs:$(abs_top_builddir)/src/lib/efreet/.libs:$(abs_top_builddir)/src/lib/efreet-mime/.libs:$(abs_top_builddir)/src/lib/efreet-trash/.libs:$(abs_top_builddir)/src/lib/eio/.libs:$(abs_top_builddir)/src/lib/elocation/.libs:$(abs_top_builddir)/src/lib/elementary/.libs
TEST_PATHS = $(abs_top_builddir)/src/lib/efl_mono:$(abs_top_builddir)/src/lib/efl_mono/.libs:$(abs_top_builddir)/src/lib/eina/.libs:$(abs_top_builddir)/src/lib/ecore/.libs:$(abs_top_builddir)/src/lib/ecore_evas/.libs:$(abs_top_builddir)/src/lib/eo/.libs:$(abs_top_builddir)/src/lib/evas/.libs:$(abs_top_builddir)/src/lib/emile/.libs:$(abs_top_builddir)/src/lib/eet/.libs:$(abs_top_builddir)/src/lib/efl/.libs:$(abs_top_builddir)/src/ecore-file/.libs:$(abs_top_builddir)/src/lib/efl-input/.libs:$(abs_top_builddir)/src/lib/edje/.libs:$(abs_top_builddir)/src/lib/ethumb/.libs:$(abs_top_builddir)/src/lib/ethumb-client/.libs:$(abs_top_builddir)/src/lib/emotion/.libs:$(abs_top_builddir)/src/lib/ecore-imf/.libs:$(abs_top_builddir)/src/lib/ecore-con/.libs:$(abs_top_builddir)/src/lib/eldbus/.libs:$(abs_top_builddir)/src/lib/efreet/.libs:$(abs_top_builddir)/src/lib/efreet-mime/.libs:$(abs_top_builddir)/src/lib/efreet-trash/.libs:$(abs_top_builddir)/src/lib/eio/.libs:$(abs_top_builddir)/src/lib/elocation/.libs:$(abs_top_builddir)/src/lib/elementary/.libs:$(abs_top_builddir)/src/tests/efl_mono/.libs
WIN_ADD_TEST_PATHS = $(abs_top_builddir)/src/lib/evil/.libs:$(abs_top_builddir)/src/lib/ecore_win32/.libs:$(abs_top_builddir)/src/lib/ector/.libs:$(abs_top_builddir)/src/lib/ecore_con/.libs:$(abs_top_builddir)/src/lib/ecore_imf/.libs:$(abs_top_builddir)/src/lib/ecore_file/.libs:$(abs_top_builddir)/src/lib/ecore_input/.libs:$(abs_top_builddir)/src/ethumb_client/.libs:$(abs_top_builddir)/src/tests/efl_mono/.libs

View File

@ -301,12 +301,15 @@ struct event_definition_generator
bool generate_event_add_remove(OutputIterator sink, attributes::event_def const &evt, const std::string& event_name, Context context) const
{
std::string upper_c_name = utils::to_uppercase(evt.c_name);
auto unit = (const Eolian_Unit*) context_find_tag<eolian_state_context>(context).state;
attributes::klass_def klass(get_klass(evt.klass, unit), unit);
auto library_name = context_find_tag<library_context>(context).actual_library_name(klass.filename);
return as_generator(
scope_tab << "{\n"
<< scope_tab << scope_tab << "add {\n"
<< scope_tab << scope_tab << scope_tab << "lock (eventLock) {\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "if (add_cpp_event_handler(key, this.evt_" << event_name << "_delegate)) {\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "if (add_cpp_event_handler(" << library_name << ", key, this.evt_" << event_name << "_delegate)) {\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "eventHandlers.AddHandler(" << event_name << "Key , value);\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "} else\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "Eina.Log.Error($\"Error adding proxy for event {key}\");\n"

View File

@ -32,41 +32,50 @@ struct native_function_definition_generator
bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
{
EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "native_function_definition_generator: " << f.c_name << std::endl;
if(blacklist::is_function_blacklisted(f, context) || f.is_static) // Only Concrete classes implement static methods.
if(blacklist::is_function_blacklisted(f, context))
return true;
else
{
if(!as_generator
("\n\n" << scope_tab
<< eolian_mono::marshall_native_annotation(true)
<< eolian_mono::marshall_annotation(true)
<< " private delegate "
<< eolian_mono::marshall_type(true)
<< " "
<< string
<< "_delegate(System.IntPtr obj, System.IntPtr pd"
<< *grammar::attribute_reorder<-1, -1>
<< "_delegate(" << (f.is_static ? "" : "System.IntPtr obj, System.IntPtr pd")
<< ((!f.is_static && f.parameters.size() > 0) ? ", " : "")
<< (grammar::attribute_reorder<-1, -1>
(
(", " << marshall_native_annotation << " " << marshall_parameter)
)
(marshall_annotation << " " << marshall_parameter)
) % ", ")
<< ");\n")
.generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
return false;
if(!as_generator
(scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(context).actual_library_name(f.filename) << ")] "
<< eolian_mono::marshall_native_annotation(true)
<< " private static extern "
("\n\n" << scope_tab
<< eolian_mono::marshall_annotation(true)
<< " public delegate "
<< eolian_mono::marshall_type(true)
<< " " << string
<< "(System.IntPtr obj"
<< *grammar::attribute_reorder<-1, -1>
<< " "
<< string << "_api_delegate(" << (f.is_static ? "" : "System.IntPtr obj")
<< ((!f.is_static && f.parameters.size() > 0) ? ", " : "")
<< (grammar::attribute_reorder<-1, -1>
(
(", " << marshall_native_annotation << " " << marshall_parameter)
)
(marshall_annotation << " " << marshall_parameter)
) % ", ")
<< ");\n")
.generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
return false;
if(!as_generator
(scope_tab
<< " public static Efl.Eo.FunctionWrapper<" << string << "_api_delegate> " << string << "_ptr = new Efl.Eo.FunctionWrapper<"
<< string << "_api_delegate>(_Module, \"" << string << "\");\n")
.generate(sink, std::make_tuple(f.c_name, f.c_name, f.c_name, f.c_name), context))
return false;
std::string return_type;
if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
return false;
@ -77,6 +86,11 @@ struct native_function_definition_generator
else
klass_cast_name = name_helpers::klass_interface_name(*klass);
std::string self = "Efl.Eo.Globals.efl_super(obj, Efl.Eo.Globals.efl_class_get(obj))";
if (f.is_static)
self = "";
if(!as_generator
(scope_tab
<< " private static "
@ -93,7 +107,8 @@ struct native_function_definition_generator
<< scope_tab << scope_tab << "if(wrapper != null) {\n"
<< scope_tab << scope_tab << scope_tab << eolian_mono::native_function_definition_preamble()
<< scope_tab << scope_tab << scope_tab << "try {\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << (return_type != " void" ? "_ret_var = " : "") << "((" << klass_cast_name << ")wrapper)." << string
<< scope_tab << scope_tab << scope_tab << scope_tab << (return_type != " void" ? "_ret_var = " : "")
<< (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")wrapper).") << string
<< "(" << (native_argument_invocation % ", ") << ");\n"
<< scope_tab << scope_tab << scope_tab << "} catch (Exception e) {\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "Eina.Log.Warning($\"Callback error: {e.ToString()}\");\n"
@ -102,7 +117,7 @@ struct native_function_definition_generator
<< eolian_mono::native_function_definition_epilogue(*klass)
<< scope_tab << scope_tab << "} else {\n"
<< scope_tab << scope_tab << scope_tab << (return_type != " void" ? "return " : "") << string
<< "(Efl.Eo.Globals.efl_super(obj, " << "Efl.Eo.Globals.efl_class_get(obj))" << *(", " << argument) << ");\n"
<< "_ptr.Value.Delegate(" << self << ((!f.is_static && f.parameters.size() > 0) ? ", " : "") << (argument % ", ") << ");\n"
<< scope_tab << scope_tab << "}\n"
<< scope_tab << "}\n"
)
@ -118,9 +133,13 @@ struct native_function_definition_generator
, context))
return false;
// Static functions do not need to be called from C
if (f.is_static)
return true;
// This is the delegate that will be passed to Eo to be called from C.
if(!as_generator(
scope_tab << "private " << f.c_name << "_delegate " << f.c_name << "_static_delegate;\n"
scope_tab << "private static " << f.c_name << "_delegate " << f.c_name << "_static_delegate;\n"
).generate(sink, attributes::unused, context))
return false;
return true;
@ -141,22 +160,6 @@ struct function_definition_generator
if(blacklist::is_function_blacklisted(f, context))
return true;
if(!as_generator
("\n\n" << scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(context).actual_library_name(f.filename) << ")]\n"
<< scope_tab << eolian_mono::marshall_annotation(true)
<< (do_super ? " protected " : " private ") << "static extern "
<< eolian_mono::marshall_type(true)
<< " " << string
<< "(" << (f.is_static ? "" : "System.IntPtr obj")
<< ((!f.is_static && (f.parameters.size() > 0)) ? ", " : "")
<< (grammar::attribute_reorder<-1, -1>
(
(marshall_annotation << " " << marshall_parameter)
) % ",")
<< ");\n")
.generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
return false;
std::string return_type;
if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
return false;
@ -176,8 +179,10 @@ struct function_definition_generator
if(!as_generator
(scope_tab << ((do_super && !f.is_static) ? "virtual " : "") << "public " << (f.is_static ? "static " : "") << return_type << " " << string << "(" << (parameter % ", ")
<< ") {\n "
<< eolian_mono::function_definition_preamble() << string << "("
<< self << ((!f.is_static && (f.parameters.size() > 0)) ? "," : "")
<< eolian_mono::function_definition_preamble()
<< klass_full_native_inherit_name(f.klass) << "." << string << "_ptr.Value.Delegate("
<< self
<< ((!f.is_static && (f.parameters.size() > 0)) ? "," : "")
<< (argument_invocation % ", ") << ");\n"
<< eolian_mono::function_definition_epilogue()
<< " }\n")

View File

@ -47,9 +47,9 @@ struct function_pointer {
.generate(sink, std::make_tuple(f, f.return_type, f_name, f.parameters), funcptr_ctx))
return false;
// "Internal" delegate, 1-to-1 with the Unamaged function type
if (!as_generator(marshall_native_annotation(true)
if (!as_generator(marshall_annotation(true)
<< "public delegate " << marshall_type(true) << " " << string // public?
<< "Internal(IntPtr data" << *grammar::attribute_reorder<-1, -1>((", " << marshall_native_annotation << " " << marshall_parameter)) << ");\n")
<< "Internal(IntPtr data" << *grammar::attribute_reorder<-1, -1>((", " << marshall_annotation << " " << marshall_parameter)) << ");\n")
.generate(sink, std::make_tuple(f.return_type, f.return_type, f_name, f.parameters), funcptr_ctx))
return false;
@ -80,8 +80,8 @@ struct function_pointer {
<< scope_tab << "}\n\n"
<< scope_tab << marshall_native_annotation(true)
<< scope_tab << "internal static " << marshall_type(true) << " Cb(IntPtr cb_data" << *grammar::attribute_reorder<-1, -1>((", " << marshall_native_annotation << " " << marshall_parameter)) << ")\n"
<< scope_tab << marshall_annotation(true)
<< scope_tab << "internal static " << marshall_type(true) << " Cb(IntPtr cb_data" << *grammar::attribute_reorder<-1, -1>((", " << marshall_annotation << " " << marshall_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"

View File

@ -37,7 +37,8 @@ struct function_registration_generator
// auto index = index_generator();
if(!as_generator(
scope_tab << scope_tab << f.c_name << "_static_delegate = new " << f.c_name << "_delegate(" <<
scope_tab << scope_tab << "if (" << f.c_name << "_static_delegate == null)\n"
<< scope_tab << scope_tab << f.c_name << "_static_delegate = new " << f.c_name << "_delegate(" <<
escape_keyword(f.name) << ");\n"
).generate(sink, attributes::unused, context))
return false;
@ -47,9 +48,9 @@ struct function_registration_generator
#ifdef _WIN32
<< "api_func = Marshal.StringToHGlobalAnsi(\"" << string << "\")"
#else
<< "api_func = Efl.Eo.Globals.dlsym(Efl.Eo.Globals.RTLD_DEFAULT, \"" << string << "\")"
<< "api_func = Efl.Eo.FunctionInterop.LoadFunctionPointer(_Module.Module, \"" << string << "\")"
#endif
", func = Marshal.GetFunctionPointerForDelegate(" << string << "_static_delegate)});\n"
<< ", func = Marshal.GetFunctionPointerForDelegate(" << string << "_static_delegate)});\n"
)
.generate(sink, std::make_tuple(f.c_name, f.c_name), context))
return false;

View File

@ -374,9 +374,10 @@ struct klass
if(!as_generator
(
"public class " << native_inherit_name << " " << (root ? ": Efl.Eo.NativeClass" : (": " + base_name)) <<"{\n"
// << scope_tab << (root ? "protected IntPtr EoKlass { get; set; }\n" : "\n")
<< scope_tab << "public " << /*(root ? "" : "new ")*/ "override " << "System.Collections.Generic.List<Efl_Op_Description> GetEoOps(System.Type type)\n"
"public class " << native_inherit_name << " " << (root ? " : Efl.Eo.NativeClass" : (": " + base_name)) <<"{\n"
<< scope_tab << "public " << (root ? "" : "new ") << " static Efl.Eo.NativeModule _Module = new Efl.Eo.NativeModule("
<< context_find_tag<library_context>(context).actual_library_name(cls.filename) << ");\n"
<< scope_tab << "public override System.Collections.Generic.List<Efl_Op_Description> GetEoOps(System.Type type)\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "var descs = new System.Collections.Generic.List<Efl_Op_Description>();\n"
)
@ -488,8 +489,6 @@ struct klass
return as_generator(
scope_tab << visibility << " System.IntPtr handle;\n"
<< scope_tab << "public Dictionary<String, IntPtr> cached_strings = new Dictionary<String, IntPtr>();" << "\n"
<< scope_tab << "public Dictionary<String, IntPtr> cached_stringshares = new Dictionary<String, IntPtr>();" << "\n"
<< scope_tab << "///<summary>Pointer to the native instance.</summary>\n"
<< scope_tab << "public System.IntPtr NativeHandle {\n"
<< scope_tab << scope_tab << "get { return handle; }\n"
@ -603,8 +602,6 @@ struct klass
<< scope_tab << "///<summary>Releases the underlying native instance.</summary>\n"
<< scope_tab << "public void Dispose()\n"
<< scope_tab << "{\n"
<< scope_tab << "Efl.Eo.Globals.free_dict_values(cached_strings);" << "\n"
<< scope_tab << "Efl.Eo.Globals.free_stringshare_values(cached_stringshares);" << "\n"
<< scope_tab << scope_tab << "Dispose(true);\n"
<< scope_tab << scope_tab << "GC.SuppressFinalize(this);\n"
<< scope_tab << "}\n"
@ -681,13 +678,13 @@ struct klass
// Callback registration functions
if (!as_generator(
scope_tab << visibility << "bool add_cpp_event_handler(string key, Efl.EventCb evt_delegate) {\n"
scope_tab << visibility << "bool add_cpp_event_handler(string lib, string key, Efl.EventCb evt_delegate) {\n"
<< scope_tab << scope_tab << "int event_count = 0;\n"
<< scope_tab << scope_tab << "if (!event_cb_count.TryGetValue(key, out event_count))\n"
<< scope_tab << scope_tab << scope_tab << "event_cb_count[key] = event_count;\n"
<< scope_tab << scope_tab << "if (event_count == 0) {\n"
<< scope_tab << scope_tab << scope_tab << "IntPtr desc = Efl.EventDescription.GetNative(key);\n"
<< scope_tab << scope_tab << scope_tab << "IntPtr desc = Efl.EventDescription.GetNative(lib, key);\n"
<< scope_tab << scope_tab << scope_tab << "if (desc == IntPtr.Zero) {\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "Eina.Log.Error($\"Failed to get native event {key}\");\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n"
@ -709,7 +706,8 @@ struct klass
<< scope_tab << scope_tab << scope_tab << "event_cb_count[key] = event_count;\n"
<< scope_tab << scope_tab << "if (event_count == 1) {\n"
<< scope_tab << scope_tab << scope_tab << "IntPtr desc = Efl.EventDescription.GetNative(key);\n"
<< scope_tab << scope_tab << scope_tab << "IntPtr desc = Efl.EventDescription.GetNative("
<< context_find_tag<library_context>(context).actual_library_name(cls.filename) << ", key);\n"
<< scope_tab << scope_tab << scope_tab << "if (desc == IntPtr.Zero) {\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "Eina.Log.Error($\"Failed to get native event {key}\");\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n"

View File

@ -90,7 +90,7 @@ struct marshall_annotation_visitor_generate
{"string", true, [&] {
return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))]";
}},
{"string", false, [&] {
{"string", nullptr, [&] {
return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))]";
}},
{"mstring", true, [&] {
@ -112,10 +112,10 @@ struct marshall_annotation_visitor_generate
return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueMarshaler))]";
}},
{"strbuf", true, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufPassOwnershipMarshaler))]";
return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufPassOwnershipMarshaler))]";
}},
{"strbuf", false, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufKeepOwnershipMarshaler))]";
return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufKeepOwnershipMarshaler))]";
}},
};
@ -169,128 +169,6 @@ struct marshall_annotation_visitor_generate
return true;
}
};
template <typename OutputIterator, typename Context>
struct marshall_native_annotation_visitor_generate
{
mutable OutputIterator sink;
Context const* context;
std::string c_type;
bool is_out;
bool is_return;
bool is_ptr;
typedef marshall_type_visitor_generate<OutputIterator, Context> visitor_type;
typedef bool result_type;
bool operator()(attributes::regular_type_def const& regular) const
{
using attributes::regular_type_def;
struct match
{
eina::optional<std::string> name;
eina::optional<bool> has_own;
std::function<std::string()> function;
};
match const parameter_match_table[] =
{
// signed primitives
{"bool", nullptr, [&] { return " [MarshalAs(UnmanagedType.U1)]"; }},
{"string", true, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))]";
}},
{"string", false, [&] {
if (is_out)
return "";
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))]";
}},
{"stringshare", true, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringsharePassOwnershipMarshaler))]";
}},
{"stringshare", false, [&] {
if (is_out)
return "";
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringshareKeepOwnershipMarshaler))]";
}},
{"strbuf", true, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufPassOwnershipMarshaler))]";
}},
{"strbuf", false, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufKeepOwnershipMarshaler))]";
}},
};
match const return_match_table[] =
{
// signed primitives
{"bool", nullptr, [&] { return " [return: MarshalAs(UnmanagedType.U1)]"; }},
{"string", true, [&] {
return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))]";
}},
{"string", false, [&] { return ""; }},
{"stringshare", true, [&] {
return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringsharePassOwnershipMarshaler))]";
}},
{"stringshare", false, [&] { return ""; }},
{"strbuf", true, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufPassOwnershipMarshaler))]";
}},
{"strbuf", false, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufKeepOwnershipMarshaler))]";
}},
};
if(eina::optional<bool> b = call_annotation_match
((is_return ? return_match_table : parameter_match_table)
, [&] (match const& m)
{
return (!m.name || *m.name == regular.base_type)
&& (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
;
}
, [&] (std::string const& string)
{
std::copy(string.begin(), string.end(), sink);
return true;
}))
{
return *b;
}
else
{
return true;
}
}
bool operator()(attributes::klass_name const& klass_name) const
{
const char *return_prefix = is_return ? "return:" : "";
const char *marshal_prefix = "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(";
std::string name = name_helpers::klass_full_concrete_name(klass_name);
if (name == "Efl.Class")
name = "Efl.Eo.MarshalEflClass";
else
{
auto own = klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag";
name = "Efl.Eo.MarshalTest<" + name + ", Efl.Eo." + own + ">";
}
return as_generator(
lit("[") << return_prefix << marshal_prefix << name << "))]"
).generate(sink, name, *context);
}
bool operator()(attributes::complex_type_def const& c) const
{
if (c.outer.base_type == "future")
{
std::string prefix = is_return ? "return: " : "";
return as_generator("[" << prefix << "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.FutureMarshaler))]").generate(sink, nullptr, *context);
}
return true;
}
};
} }
#endif

View File

@ -13,8 +13,6 @@ template <typename OutputIterator, typename Context>
struct marshall_type_visitor_generate;
template <typename OutputIterator, typename Context>
struct marshall_annotation_visitor_generate;
template <typename OutputIterator, typename Context>
struct marshall_native_annotation_visitor_generate;
}
/*
@ -73,26 +71,6 @@ struct marshall_annotation_generator
bool is_return;
};
struct marshall_native_annotation_generator
{
marshall_native_annotation_generator(bool is_return = false)
: is_return(is_return) {}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
{
return type.original_type.visit(detail::marshall_native_annotation_visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr});
}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
return param.type.original_type.visit(detail::marshall_native_annotation_visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
, param.direction != attributes::parameter_direction::in, false, param.type.is_ptr});
}
bool is_return;
};
struct marshall_type_terminal
{
marshall_type_generator const operator()(bool is_return) const
@ -120,19 +98,6 @@ marshall_annotation_generator const as_generator(marshall_annotation_terminal)
}
struct marshall_native_annotation_terminal
{
marshall_native_annotation_generator const operator()(bool is_return) const
{
return marshall_native_annotation_generator(is_return);
}
} const marshall_native_annotation = {};
marshall_native_annotation_generator const as_generator(marshall_native_annotation_terminal)
{
return marshall_native_annotation_generator{};
}
}
namespace efl { namespace eolian { namespace grammar {
@ -158,23 +123,12 @@ struct is_generator< ::eolian_mono::marshall_annotation_generator> : std::true_t
template <>
struct is_generator< ::eolian_mono::marshall_annotation_terminal> : std::true_type {};
template <>
struct is_eager_generator< ::eolian_mono::marshall_native_annotation_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::marshall_native_annotation_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::marshall_native_annotation_terminal> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::marshall_annotation_generator> : std::integral_constant<int, 1> {};
template <>
struct attributes_needed< ::eolian_mono::marshall_annotation_terminal> : std::integral_constant<int, 1> {};
template <>
struct attributes_needed< ::eolian_mono::marshall_native_annotation_generator> : std::integral_constant<int, 1> {};
template <>
struct attributes_needed< ::eolian_mono::marshall_native_annotation_terminal> : std::integral_constant<int, 1> {};
}
} } }

View File

@ -32,7 +32,6 @@ struct marshall_type_visitor_generate
bool operator()(attributes::regular_type_def const& regular) const
{
using attributes::regular_type_def;
bool is_inherit_native = context_find_tag<class_context>(*context).current_wrapper_kind == class_context::inherit_native;
struct match
{
@ -47,32 +46,24 @@ struct marshall_type_visitor_generate
{
regular_type_def r = regular;
r.base_qualifier.qualifier ^= qualifier_info::is_ref;
// if(is_out || is_return)
return replace_base_type(r, " System.String");
// else return replace_base_type(r, " ::efl::eina::string_view");
}}
, {"string", false, [&]
{
regular_type_def r = regular;
r.base_qualifier.qualifier ^= qualifier_info::is_ref;
if (is_inherit_native && (is_return || is_out))
return replace_base_type(r, " System.IntPtr");
return replace_base_type(r, " System.String");
}}
, {"mstring", true, [&]
{
regular_type_def r = regular;
r.base_qualifier.qualifier ^= qualifier_info::is_ref;
// if(is_out || is_return)
return replace_base_type(r, " System.String");
// else return replace_base_type(r, " ::efl::eina::string_view");
}}
, {"mstring", false, [&]
{
regular_type_def r = regular;
r.base_qualifier.qualifier ^= qualifier_info::is_ref;
if (is_inherit_native && (is_return || is_out))
return replace_base_type(r, " System.IntPtr");
return replace_base_type(r, " System.String");
}}
, {"stringshare", true, [&]
@ -85,10 +76,7 @@ struct marshall_type_visitor_generate
{
regular_type_def r = regular;
r.base_qualifier.qualifier ^= qualifier_info::is_ref;
if (is_inherit_native && (is_return || is_out))
return replace_base_type(r, " System.IntPtr");
else
return replace_base_type(r, " System.String");
return replace_base_type(r, " System.String");
}}
, {"strbuf", nullptr, [&]
{
@ -193,7 +181,6 @@ struct marshall_type_visitor_generate
bool operator()(attributes::klass_name klass_name) const
{
return visitor_generate<OutputIterator, Context>{sink, context, c_type, is_out, is_return, is_ptr}(klass_name);
// return as_generator(" System.IntPtr").generate(sink, attributes::unused, *context);
}
bool operator()(attributes::complex_type_def const& complex) const
{
@ -237,14 +224,8 @@ struct marshall_type_visitor_generate
auto default_match = [&] (attributes::complex_type_def const& complex)
{
regular_type_def no_pointer_regular = complex.outer;
// std::vector<attributes::pointer_indirection> pointers;
// pointers.swap(no_pointer_regular.pointers);
// if(is_out)
// pointers.push_back({{attributes::qualifier_info::is_none, {}}, true});
return visitor_type{sink, context, c_type, false}(no_pointer_regular)
&& as_generator("<" << (type % ", ") << ">").generate(sink, complex.subtypes, *context)
;
// && detail::generate_pointers(sink, pointers, *context, false);
&& as_generator("<" << (type % ", ") << ">").generate(sink, complex.subtypes, *context);
};
if(eina::optional<bool> b = call_match
@ -269,12 +250,9 @@ struct marshall_type_visitor_generate
return *b;
}
//return default_match(complex);
return visitor_generate<OutputIterator, Context>{sink, context, c_type, is_out, is_return, is_ptr}(complex);
// return as_generator(" System.IntPtr").generate(sink, attributes::unused, *context);
}
};
} }
#endif

View File

@ -364,13 +364,27 @@ inline std::string klass_inherit_name(T const& klass)
template<typename T>
inline std::string klass_native_inherit_name(T const& klass)
{
return klass_concrete_name(klass) + "NativeInherit";
switch(klass.type)
{
case attributes::class_type::abstract_:
case attributes::class_type::regular:
return klass_concrete_name(klass) + "NativeInherit";
default:
return klass_interface_name(klass) + "NativeInherit";
}
}
template<typename T>
inline std::string klass_full_native_inherit_name(T const& klass)
{
return klass_full_concrete_name(klass) + "NativeInherit";
switch(klass.type)
{
case attributes::class_type::abstract_:
case attributes::class_type::regular:
return klass_full_concrete_name(klass) + "NativeInherit";
default:
return klass_full_interface_name(klass) + "NativeInherit";
}
}
template<typename T>

View File

@ -1112,7 +1112,7 @@ struct native_convert_out_assign_generator
return false;
}
return as_generator(
string << "= Efl.Eo.Globals.cached_stringshare_to_intptr(((" << name_helpers::klass_inherit_name(*klass) << ")wrapper).cached_stringshares, " << string << ");\n"
string << "= " << string << ";\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context);
}
else if (param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT))
@ -1123,7 +1123,7 @@ struct native_convert_out_assign_generator
return false;
}
return as_generator(
string << "= Efl.Eo.Globals.cached_string_to_intptr(((" << name_helpers::klass_inherit_name(*klass) << ")wrapper).cached_strings, " << string << ");\n"
string << " = " << string << ";\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context);
}
else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
@ -1253,7 +1253,7 @@ struct native_convert_return_generator
return false;
}
return as_generator(
"return Efl.Eo.Globals.cached_string_to_intptr(((" << name_helpers::klass_inherit_name(*klass) << ")wrapper).cached_strings, _ret_var);\n"
"return _ret_var;\n"
).generate(sink, attributes::unused, context);
}
else
@ -1271,7 +1271,7 @@ struct native_convert_return_generator
return false;
}
return as_generator(
"return Efl.Eo.Globals.cached_stringshare_to_intptr(((" << name_helpers::klass_inherit_name(*klass) << ")wrapper).cached_stringshares, _ret_var);\n"
"return _ret_var;\n"
).generate(sink, attributes::unused, context);
}
else

View File

@ -24,7 +24,7 @@ struct part_definition_generator
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "get\n"
<< scope_tab << scope_tab << "{\n"
<< scope_tab << scope_tab << scope_tab << "Efl.Object obj = efl_part_get(NativeHandle, \"" << part.name << "\");\n"
<< scope_tab << scope_tab << scope_tab << "Efl.Object obj = Efl.PartNativeInherit.efl_part_get_ptr.Value.Delegate(NativeHandle, \"" << part.name << "\");\n"
<< scope_tab << scope_tab << scope_tab << "return " << part_klass_name << ".static_cast(obj);\n"
<< scope_tab << scope_tab << "}\n"
<< scope_tab << "}\n"

View File

@ -131,6 +131,22 @@ struct struct_internal_definition_generator
.generate(sink, nullptr, context))
return false;
}
else if (regular && !(regular->base_qualifier & efl::eolian::grammar::attributes::qualifier_info::is_ref)
&& regular->base_type == "bool")
{
if (!as_generator("///<summary>Internal wrapper for field " << field_name << "</summary>\n"
"public System.Byte " << field_name << ";\n")
.generate(sink, nullptr, context))
return false;
}
else if (regular && !(regular->base_qualifier & efl::eolian::grammar::attributes::qualifier_info::is_ref)
&& regular->base_type == "char")
{
if (!as_generator("///<summary>Internal wrapper for field " << field_name << "</summary>\n"
"public System.Byte " << field_name << ";\n")
.generate(sink, nullptr, context))
return false;
}
else if (!as_generator(scope_tab << eolian_mono::marshall_annotation(false) << "\n"
<< scope_tab << "public " << eolian_mono::marshall_type(false) << " " << string << ";\n")
.generate(sink, std::make_tuple(field.type, field.type, field_name), context))
@ -255,6 +271,20 @@ struct to_internal_field_convert_generator
).generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if (!field.type.is_ptr && regular && regular->base_type == "bool")
{
if (!as_generator(
scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << " ? (byte)1 : (byte)0;\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if (!field.type.is_ptr && regular && regular->base_type == "char")
{
if (!as_generator(
scope_tab << scope_tab << "_internal_struct." << string << " = (byte)_external_struct." << string << ";\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else // primitives and enums
{
if (!as_generator(
@ -358,6 +388,20 @@ struct to_external_field_convert_generator
).generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if (!field.type.is_ptr && regular && regular->base_type == "bool")
{
if (!as_generator(
scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << " != 0;\n"
).generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else if (!field.type.is_ptr && regular && regular->base_type == "char")
{
if (!as_generator(
scope_tab << scope_tab << "_external_struct." << string << " = (char)_internal_struct." << string << ";\n"
).generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
else // primitives and enums
{
if (!as_generator(

View File

@ -6,6 +6,7 @@
#include <utility>
#include <type_traits>
#include <tuple>
#include <iosfwd>
#include <eina_aligned_union.hh>
@ -149,6 +150,17 @@ struct destroy_visitor
}
};
struct ostream_visitor
{
std::ostream* s;
typedef std::ostream& result_type;
template <typename T>
std::ostream& operator()(T const& other) const
{
return *s << other;
}
};
template <typename T>
struct get_visitor
{
@ -295,6 +307,10 @@ private:
&& (rhs.type == -1
|| rhs.visit(compare_equal_visitor{&lhs.buffer}));
}
friend std::ostream& operator<<(std::ostream& s, variant<Args...> const& rhs)
{
return rhs.visit(ostream_visitor{&s});
}
int type;
/**

View File

@ -9,15 +9,31 @@ using static Efl.UnsafeNativeMethods;
namespace Efl {
static class UnsafeNativeMethods {
private delegate void init_func_delegate();
[DllImport(efl.Libs.Ecore)] public static extern void ecore_init();
[DllImport(efl.Libs.Ecore)] public static extern void ecore_shutdown();
[DllImport(efl.Libs.Evas)] public static extern void evas_init();
// dotnet loads libraries from DllImport with RTLD_LOCAL. Due to the
// way evas modules are built with meson, currently they do not link directly
// with libevas, leading to symbol not found errors when trying to open them.
// The call to FunctionWrapper makes sure evas is loaded with RTLD_GLOBAL,
// allowing the symbols to remain visible for the modules until the build
// is sorted out.
private static Efl.Eo.FunctionWrapper<init_func_delegate> _evas_init;
[DllImport(efl.Libs.Evas)] public static extern void evas_shutdown();
[DllImport(efl.Libs.Elementary)] public static extern int elm_init(int argc, IntPtr argv);
[DllImport(efl.Libs.Elementary)] public static extern void elm_policy_set(int policy, int policy_detail);
[DllImport(efl.Libs.Elementary)] public static extern void elm_shutdown();
[DllImport(efl.Libs.Elementary)] public static extern void elm_run();
[DllImport(efl.Libs.Elementary)] public static extern void elm_exit();
static UnsafeNativeMethods() {
_evas_init = new Efl.Eo.FunctionWrapper<init_func_delegate>("evas", "evas_init");
}
public static void evas_init()
{
_evas_init.Value.Delegate();
}
}
public enum Components {

View File

@ -17,6 +17,22 @@ public class Libs {
public const string Eldbus = "@ELDBUS_DL_MONO@";
public const string CustomExports = "@CUSTOM_EXPORTS_MONO_DL_MONO@";
public const string Libdl = "libdl.so";
public const string Kernel32 = "kernel32.dll";
public static Efl.Eo.NativeModule EflModule = new Efl.Eo.NativeModule(Efl);
public static Efl.Eo.NativeModule CoreModule = new Efl.Eo.NativeModule(Ecore);
public static Efl.Eo.NativeModule EinaModule = new Efl.Eo.NativeModule(Eina);
public static Efl.Eo.NativeModule EoModule = new Efl.Eo.NativeModule(Eo);
public static Efl.Eo.NativeModule EvasModule = new Efl.Eo.NativeModule(Evas);
public static Efl.Eo.NativeModule EvilModule = new Efl.Eo.NativeModule(Evil);
public static Efl.Eo.NativeModule EdjeModule = new Efl.Eo.NativeModule(Edje);
public static Efl.Eo.NativeModule ElementaryModule = new Efl.Eo.NativeModule(Elementary);
public static Efl.Eo.NativeModule EldbusModule = new Efl.Eo.NativeModule(Eldbus);
public static Efl.Eo.NativeModule CustomExportsModule = new Efl.Eo.NativeModule(CustomExports);
public static Efl.Eo.NativeModule LibdlModule = new Efl.Eo.NativeModule(Libdl);
public static Efl.Eo.NativeModule Kernel32Module = new Efl.Eo.NativeModule(Kernel32);
}
}

View File

@ -95,12 +95,6 @@ public static class MemoryNative {
}
}
[StructLayout(LayoutKind.Sequential)]
public struct ConvertWrapper<T>
{
public T val;
}
public static class PrimitiveConversion
{
public static T PointerToManaged<T>(IntPtr nat)
@ -111,8 +105,8 @@ public static class PrimitiveConversion
return default(T);
}
var w = Marshal.PtrToStructure<Eina.ConvertWrapper<T> >(nat);
return w.val;
var w = Marshal.PtrToStructure<T>(nat);
return w;
}
public static IntPtr ManagedToPointerAlloc<T>(T man)

View File

@ -10,17 +10,11 @@ using static Eina.HashNativeFunctions;
using static Eina.InarrayNativeFunctions;
using static Eina.InlistNativeFunctions;
using static Eina.NativeCustomExportFunctions;
using static Eina.ContainerCommonData;
namespace Eina {
public enum ElementType { NumericType, StringType, ObjectType };
public static class ContainerCommonData
{
public static IBaseElementTraits<IntPtr> intPtrTraits = null;
}
[StructLayout(LayoutKind.Sequential)]
public struct InlistMem
{
@ -36,21 +30,17 @@ public struct InlistNode<T>
public T Val {get;set;}
}
public interface IBaseElementTraits<T>
{
IntPtr ManagedToNativeAlloc(T man);
IntPtr ManagedToNativeAllocRef(T man, bool refs);
IntPtr ManagedToNativeAllocInlistNode(T man);
IntPtr ManagedToNativeAllocInplace(T man);
void ManagedToNativeCopyTo(T man, IntPtr mem);
void NativeFree(IntPtr nat);
void NativeFreeRef(IntPtr nat, bool unrefs);
void NativeFreeInlistNodeElement(IntPtr nat);
void NativeFreeInlistNode(IntPtr nat, bool freeElement);
void NativeFreeInplace(IntPtr nat);
void ResidueFreeInplace(IntPtr nat);
T NativeToManaged(IntPtr nat);
T NativeToManagedRef(IntPtr nat);
T NativeToManagedInlistNode(IntPtr nat);
T NativeToManagedInplace(IntPtr nat);
IntPtr EinaCompareCb();
@ -60,40 +50,33 @@ public interface IBaseElementTraits<T>
IntPtr EinaHashIteratorKeyNew(IntPtr hash);
}
public class StringElementTraits<T> : IBaseElementTraits<T>
public class StringElementTraits : IBaseElementTraits<string>
{
public StringElementTraits()
{
if (intPtrTraits == null)
intPtrTraits = TraitFunctions.GetTypeTraits<IntPtr>();
}
public IntPtr ManagedToNativeAlloc(T man)
public IntPtr ManagedToNativeAlloc(string man)
{
return MemoryNative.StrDup((string)(object)man);
IntPtr newstring = MemoryNative.StrDup(man);
return newstring;
}
public IntPtr ManagedToNativeAllocRef(T man, bool refs)
{
// Keep alloc on C# ?
return ManagedToNativeAlloc(man);
}
public IntPtr ManagedToNativeAllocInlistNode(T man)
public IntPtr ManagedToNativeAllocInlistNode(string man)
{
var node = new InlistNode<IntPtr>();
node.Val = ManagedToNativeAlloc(man);
GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
IntPtr ptr = pinnedData.AddrOfPinnedObject();
IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<InlistNode<IntPtr> >());
IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<InlistMem>() + Marshal.SizeOf<IntPtr>());
pinnedData.Free();
return nat;
}
public IntPtr ManagedToNativeAllocInplace(T man)
public void ManagedToNativeCopyTo(string man, IntPtr mem)
{
return intPtrTraits.ManagedToNativeAlloc(ManagedToNativeAlloc(man));
IntPtr stringptr = ManagedToNativeAlloc(man);
Marshal.WriteIntPtr(mem, stringptr);
}
public void NativeFree(IntPtr nat)
@ -102,17 +85,13 @@ public class StringElementTraits<T> : IBaseElementTraits<T>
MemoryNative.Free(nat);
}
public void NativeFreeRef(IntPtr nat, bool unrefs)
{
NativeFree(nat);
}
public void NativeFreeInlistNodeElement(IntPtr nat)
{
if (nat == IntPtr.Zero)
return;
var node = Marshal.PtrToStructure< InlistNode<IntPtr> >(nat);
NativeFree(node.Val);
var val = Marshal.PtrToStructure<IntPtr>
(nat + Marshal.SizeOf<InlistMem>());
NativeFree(val);
}
public void NativeFreeInlistNode(IntPtr nat, bool freeElement)
@ -131,37 +110,35 @@ public class StringElementTraits<T> : IBaseElementTraits<T>
public void ResidueFreeInplace(IntPtr nat)
{
intPtrTraits.NativeFree(nat);
}
public T NativeToManaged(IntPtr nat)
public string NativeToManaged(IntPtr nat)
{
if (nat == IntPtr.Zero)
return default(T);
return (T)(object)StringConversion.NativeUtf8ToManagedString(nat);
return default(string);
return StringConversion.NativeUtf8ToManagedString(nat);
}
public T NativeToManagedRef(IntPtr nat)
{
return NativeToManaged(nat);
}
public T NativeToManagedInlistNode(IntPtr nat)
public string NativeToManagedInlistNode(IntPtr nat)
{
if (nat == IntPtr.Zero)
{
Eina.Log.Error("Null pointer for Inlist node.");
return default(T);
return default(string);
}
var w = Marshal.PtrToStructure< InlistNode<IntPtr> >(nat);
return NativeToManaged(w.Val);
IntPtr ptr_location = nat + Marshal.SizeOf<InlistMem>();
return NativeToManaged(Marshal.ReadIntPtr(ptr_location));
}
public T NativeToManagedInplace(IntPtr nat)
// Strings inplaced are always a pointer, because they are variable-sized
public string NativeToManagedInplace(IntPtr nat)
{
if (nat == IntPtr.Zero)
return default(T);
return NativeToManaged(intPtrTraits.NativeToManaged(nat));
return default(string);
nat = Marshal.ReadIntPtr(nat);
if (nat == IntPtr.Zero)
return default(string);
return NativeToManaged(nat);
}
public IntPtr EinaCompareCb()
@ -196,9 +173,6 @@ public class EflObjectElementTraits<T> : IBaseElementTraits<T>
public EflObjectElementTraits(System.Type concrete)
{
if (intPtrTraits == null)
intPtrTraits = TraitFunctions.GetTypeTraits<IntPtr>();
concreteType = concrete;
}
@ -210,26 +184,21 @@ public class EflObjectElementTraits<T> : IBaseElementTraits<T>
return Efl.Eo.Globals.efl_ref(h);
}
public IntPtr ManagedToNativeAllocRef(T man, bool refs)
{
IntPtr h = refs ? ManagedToNativeAlloc(man) : ((Efl.Eo.IWrapper)man).NativeHandle;
return intPtrTraits.ManagedToNativeAlloc(h);
}
public IntPtr ManagedToNativeAllocInlistNode(T man)
{
var node = new InlistNode<IntPtr>();
node.Val = ManagedToNativeAlloc(man);
GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
IntPtr ptr = pinnedData.AddrOfPinnedObject();
IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<InlistNode<IntPtr> >());
IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<InlistMem>() + Marshal.SizeOf<IntPtr>());
pinnedData.Free();
return nat;
}
public IntPtr ManagedToNativeAllocInplace(T man)
public void ManagedToNativeCopyTo(T man, IntPtr mem)
{
return intPtrTraits.ManagedToNativeAlloc(ManagedToNativeAlloc(man));
IntPtr v = ManagedToNativeAlloc(man);
Marshal.WriteIntPtr(mem, v);
}
public void NativeFree(IntPtr nat)
@ -241,16 +210,16 @@ public class EflObjectElementTraits<T> : IBaseElementTraits<T>
public void NativeFreeRef(IntPtr nat, bool unrefs)
{
if (unrefs)
NativeFree(intPtrTraits.NativeToManaged(nat));
intPtrTraits.NativeFree(nat);
NativeFree(nat);
}
public void NativeFreeInlistNodeElement(IntPtr nat)
{
if (nat == IntPtr.Zero)
return;
var node = Marshal.PtrToStructure< InlistNode<IntPtr> >(nat);
NativeFree(node.Val);
var val = Marshal.PtrToStructure<IntPtr>
(nat + Marshal.SizeOf<InlistMem>());
NativeFree(val);
}
public void NativeFreeInlistNode(IntPtr nat, bool freeElement)
@ -264,12 +233,11 @@ public class EflObjectElementTraits<T> : IBaseElementTraits<T>
public void NativeFreeInplace(IntPtr nat)
{
NativeFree(intPtrTraits.NativeToManaged(nat));
NativeFree(nat);
}
public void ResidueFreeInplace(IntPtr nat)
{
intPtrTraits.NativeFree(nat);
}
public T NativeToManaged(IntPtr nat)
@ -283,7 +251,7 @@ public class EflObjectElementTraits<T> : IBaseElementTraits<T>
{
if (nat == IntPtr.Zero)
return default(T);
return NativeToManaged(intPtrTraits.NativeToManaged(nat));
return NativeToManaged(nat);
}
public T NativeToManagedInlistNode(IntPtr nat)
@ -293,15 +261,19 @@ public class EflObjectElementTraits<T> : IBaseElementTraits<T>
Eina.Log.Error("Null pointer for Inlist node.");
return default(T);
}
var w = Marshal.PtrToStructure< InlistNode<IntPtr> >(nat);
return NativeToManaged(w.Val);
IntPtr ptr_location = nat + Marshal.SizeOf<InlistMem>();
return NativeToManaged(Marshal.ReadIntPtr(ptr_location));
}
// EFL objects inplaced are always a pointer, because they are variable-sized
public T NativeToManagedInplace(IntPtr nat)
{
if (nat == IntPtr.Zero)
return default(T);
return NativeToManaged(intPtrTraits.NativeToManaged(nat));
nat = Marshal.ReadIntPtr(nat);
if (nat == IntPtr.Zero)
return default(T);
return NativeToManaged(nat);
}
public IntPtr EinaCompareCb()
@ -345,16 +317,12 @@ public abstract class PrimitiveElementTraits<T>
node.Val = man;
GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
IntPtr ptr = pinnedData.AddrOfPinnedObject();
IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf< InlistNode<T> >());
int Tsize = Marshal.SizeOf<T>() < Marshal.SizeOf<IntPtr>() ? Marshal.SizeOf<IntPtr>() : Marshal.SizeOf<T>();
IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<InlistMem>() + Tsize);
pinnedData.Free();
return nat;
}
public IntPtr ManagedToNativeAllocInplace(T man)
{
return ManagedToNativeAlloc(man);
}
public void NativeFree(IntPtr nat)
{
MemoryNative.Free(nat);
@ -395,16 +363,6 @@ public abstract class PrimitiveElementTraits<T>
return NativeToManaged(nat);
}
public T NativeToManagedInlistNode(IntPtr nat)
{
if (nat == IntPtr.Zero)
{
Eina.Log.Error("Null pointer for Inlist node.");
return default(T);
}
var w = Marshal.PtrToStructure< InlistNode<T> >(nat);
return w.Val;
}
public T NativeToManagedInplace(IntPtr nat)
{
@ -441,7 +399,7 @@ public abstract class PrimitiveElementTraits<T>
}
}
public class Primitive32ElementTraits<T> : PrimitiveElementTraits<T>, IBaseElementTraits<T>
abstract public class Primitive32ElementTraits<T> : PrimitiveElementTraits<T>, IBaseElementTraits<T>
{
private static IBaseElementTraits<Int32> int32Traits = null;
@ -454,6 +412,9 @@ public class Primitive32ElementTraits<T> : PrimitiveElementTraits<T>, IBaseEleme
int32Traits = TraitFunctions.GetTypeTraits<Int32>();
}
public abstract void ManagedToNativeCopyTo(T man, IntPtr mem);
public abstract T NativeToManagedInlistNode(IntPtr nat);
public IntPtr ManagedToNativeAllocRef(T man, bool refs)
{
return int32Traits.ManagedToNativeAlloc(Convert.ToInt32((object)man));
@ -470,7 +431,7 @@ public class Primitive32ElementTraits<T> : PrimitiveElementTraits<T>, IBaseEleme
}
}
public class Primitive64ElementTraits<T> : PrimitiveElementTraits<T>, IBaseElementTraits<T>
abstract public class Primitive64ElementTraits<T> : PrimitiveElementTraits<T>, IBaseElementTraits<T>
{
private static IBaseElementTraits<Int64> int64Traits = null;
@ -483,6 +444,9 @@ public class Primitive64ElementTraits<T> : PrimitiveElementTraits<T>, IBaseEleme
int64Traits = TraitFunctions.GetTypeTraits<Int64>();
}
public abstract void ManagedToNativeCopyTo(T man, IntPtr mem);
public abstract T NativeToManagedInlistNode(IntPtr nat);
public IntPtr ManagedToNativeAllocRef(T man, bool refs)
{
return int64Traits.ManagedToNativeAlloc(Convert.ToInt64((object)man));
@ -499,6 +463,159 @@ public class Primitive64ElementTraits<T> : PrimitiveElementTraits<T>, IBaseEleme
}
}
public class IntElementTraits : Primitive32ElementTraits<int>, IBaseElementTraits<int>
{
override public void ManagedToNativeCopyTo(int man, IntPtr mem)
{
var arr = new int[1];
arr[0] = man;
Marshal.Copy(arr, 0, mem, 1);
}
override public int NativeToManagedInlistNode(IntPtr nat)
{
if (nat == IntPtr.Zero)
{
Eina.Log.Error("Null pointer for Inlist node.");
return default(int);
}
IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
var v = new int[1];
Marshal.Copy(loc, v, 0, 1);
return v[0];
}
}
public class CharElementTraits : Primitive32ElementTraits<char>, IBaseElementTraits<char>
{
override public void ManagedToNativeCopyTo(char man, IntPtr mem)
{
var arr = new char[1];
arr[0] = man;
Marshal.Copy(arr, 0, mem, 1);
}
override public char NativeToManagedInlistNode(IntPtr nat)
{
if (nat == IntPtr.Zero)
{
Eina.Log.Error("Null pointer for Inlist node.");
return default(char);
}
IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
var v = new char[1];
Marshal.Copy(loc, v, 0, 1);
return v[0];
}
}
public class LongElementTraits : Primitive64ElementTraits<long>, IBaseElementTraits<long>
{
override public void ManagedToNativeCopyTo(long man, IntPtr mem)
{
var arr = new long[1];
arr[0] = man;
Marshal.Copy(arr, 0, mem, 1);
}
override public long NativeToManagedInlistNode(IntPtr nat)
{
if (nat == IntPtr.Zero)
{
Eina.Log.Error("Null pointer for Inlist node.");
return default(long);
}
IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
var v = new long[1];
Marshal.Copy(loc, v, 0, 1);
return v[0];
}
}
public class ShortElementTraits : Primitive32ElementTraits<short>, IBaseElementTraits<short>
{
override public void ManagedToNativeCopyTo(short man, IntPtr mem)
{
var arr = new short[1];
arr[0] = man;
Marshal.Copy(arr, 0, mem, 1);
}
override public short NativeToManagedInlistNode(IntPtr nat)
{
if (nat == IntPtr.Zero)
{
Eina.Log.Error("Null pointer for Inlist node.");
return default(short);
}
IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
var v = new short[1];
Marshal.Copy(loc, v, 0, 1);
return v[0];
}
}
public class FloatElementTraits : Primitive32ElementTraits<float>, IBaseElementTraits<float>
{
override public void ManagedToNativeCopyTo(float man, IntPtr mem)
{
var arr = new float[1];
arr[0] = man;
Marshal.Copy(arr, 0, mem, 1);
}
override public float NativeToManagedInlistNode(IntPtr nat)
{
if (nat == IntPtr.Zero)
{
Eina.Log.Error("Null pointer for Inlist node.");
return default(float);
}
IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
var v = new float[1];
Marshal.Copy(loc, v, 0, 1);
return v[0];
}
}
public class DoubleElementTraits : Primitive64ElementTraits<double>, IBaseElementTraits<double>
{
override public void ManagedToNativeCopyTo(double man, IntPtr mem)
{
var arr = new double[1];
arr[0] = man;
Marshal.Copy(arr, 0, mem, 1);
}
override public double NativeToManagedInlistNode(IntPtr nat)
{
if (nat == IntPtr.Zero)
{
Eina.Log.Error("Null pointer for Inlist node.");
return default(double);
}
IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
var v = new double[1];
Marshal.Copy(loc, v, 0, 1);
return v[0];
}
}
public class ByteElementTraits : Primitive32ElementTraits<byte>, IBaseElementTraits<byte>
{
override public void ManagedToNativeCopyTo(byte man, IntPtr mem)
{
var arr = new byte[1];
arr[0] = man;
Marshal.Copy(arr, 0, mem, 1);
}
override public byte NativeToManagedInlistNode(IntPtr nat)
{
if (nat == IntPtr.Zero)
{
Eina.Log.Error("Null pointer for Inlist node.");
return default(byte);
}
IntPtr loc = nat + Marshal.SizeOf<InlistMem>();
var v = new byte[1];
Marshal.Copy(loc, v, 0, 1);
return v[0];
}
}
public static class TraitFunctions
{
public static bool IsEflObject(System.Type type)
@ -539,6 +656,7 @@ public static class TraitFunctions
public static object RegisterTypeTraits<T>()
{
Eina.Log.Debug($"Finding TypeTraits for {typeof(T).Name}");
object traits;
var type = typeof(T);
if (IsEflObject(type))
@ -549,13 +667,25 @@ public static class TraitFunctions
traits = new EflObjectElementTraits<T>(concrete);
}
else if (IsString(type))
traits = new StringElementTraits<T>();
traits = new StringElementTraits();
else if (type.IsValueType)
{
if (Marshal.SizeOf<T>() <= 4)
traits = new Primitive32ElementTraits<T>();
if (type == typeof(int))
traits = new IntElementTraits();
else if (type == typeof(char))
traits = new CharElementTraits();
else if (type == typeof(long))
traits = new LongElementTraits();
else if (type == typeof(short))
traits = new ShortElementTraits();
else if (type == typeof(float))
traits = new FloatElementTraits();
else if (type == typeof(double))
traits = new DoubleElementTraits();
else if (type == typeof(byte))
traits = new ByteElementTraits();
else
traits = new Primitive64ElementTraits<T>();
throw new Exception("No traits registered for this type");
}
else
throw new Exception("No traits registered for this type");
@ -589,14 +719,9 @@ public static class TraitFunctions
return GetTypeTraits<T>().ManagedToNativeAlloc(man);
}
public static IntPtr ManagedToNativeAllocRef<T>(T man, bool refs = false)
public static void ManagedToNativeCopyTo<T>(T man, IntPtr mem)
{
return GetTypeTraits<T>().ManagedToNativeAllocRef(man, refs);
}
public static IntPtr ManagedToNativeAllocInplace<T>(T man)
{
return GetTypeTraits<T>().ManagedToNativeAllocInplace(man);
GetTypeTraits<T>().ManagedToNativeCopyTo(man, mem);
}
public static IntPtr ManagedToNativeAllocInlistNode<T>(T man)
@ -609,11 +734,6 @@ public static class TraitFunctions
GetTypeTraits<T>().NativeFree(nat);
}
public static void NativeFreeRef<T>(IntPtr nat, bool unrefs = false)
{
GetTypeTraits<T>().NativeFreeRef(nat, unrefs);
}
public static void NativeFreeInlistNodeElement<T>(IntPtr nat)
{
GetTypeTraits<T>().NativeFreeInlistNodeElement(nat);
@ -639,11 +759,6 @@ public static class TraitFunctions
return GetTypeTraits<T>().NativeToManaged(nat);
}
public static T NativeToManagedRef<T>(IntPtr nat)
{
return GetTypeTraits<T>().NativeToManagedRef(nat);
}
public static T NativeToManagedInlistNode<T>(IntPtr nat)
{
return GetTypeTraits<T>().NativeToManagedInlistNode(nat);

View File

@ -242,10 +242,13 @@ public class Hash<TKey, TValue> : IEnumerable<KeyValuePair<TKey,TValue>>, IDi
public bool AddNew(TKey key, TValue val)
{
var nk = ManagedToNativeAllocRef(key, true);
var nv = ManagedToNativeAlloc(val);
IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
IntPtr gchnv = CopyNativeObject(val, false);
IntPtr nv = GetNativePtr<TValue>(gchnv, false);
var r = eina_hash_add(Handle, nk, nv);
NativeFreeRef<TKey>(nk);
FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
FreeNativeIndirection<TValue>(gchnv, false);
return r;
}
@ -256,17 +259,20 @@ public class Hash<TKey, TValue> : IEnumerable<KeyValuePair<TKey,TValue>>, IDi
public bool DelByKey(TKey key)
{
var nk = ManagedToNativeAllocRef(key);
IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
var r = eina_hash_del_by_key(Handle, nk);
NativeFreeRef<TKey>(nk, OwnKey && r);
FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
// NativeFreeRef<TKey>(nk, OwnKey && r);
return r;
}
public bool DelByValue(TValue val)
{
var nv = ManagedToNativeAlloc(val);
IntPtr gchnv = CopyNativeObject(val, false);
IntPtr nv = GetNativePtr<TValue>(gchnv, false);
var r = eina_hash_del_by_data(Handle, nv);
NativeFree<TValue>(nv);
FreeNativeIndirection<TValue>(gchnv, false);
return r;
}
@ -277,42 +283,52 @@ public class Hash<TKey, TValue> : IEnumerable<KeyValuePair<TKey,TValue>>, IDi
public TValue Find(TKey key)
{
var nk = ManagedToNativeAllocRef(key);
var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
var found = eina_hash_find(Handle, nk);
NativeFreeRef<TKey>(nk);
//NativeFreeRef<TKey>(nk);
FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
if (found == IntPtr.Zero)
throw new KeyNotFoundException();
return NativeToManaged<TValue>(found);
return NativeToManaged<TValue>(IndirectNative<TValue>(found, false));
}
public bool TryGetValue(TKey key, out TValue val)
{
var nk = ManagedToNativeAllocRef(key);
var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
var found = eina_hash_find(Handle, nk);
NativeFreeRef<TKey>(nk);
FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
if (found == IntPtr.Zero)
{
val = default(TValue);
return false;
}
val = NativeToManaged<TValue>(found);
val = NativeToManaged<TValue>(IndirectNative<TValue>(found, false));
return true;
}
public bool ContainsKey(TKey key)
{
var nk = ManagedToNativeAllocRef(key);
var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
// var nk = ManagedToNativeAllocRef(key);
var found = eina_hash_find(Handle, nk);
NativeFreeRef<TKey>(nk);
// NativeFreeRef<TKey>(nk);
FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
return found != IntPtr.Zero;
}
public bool Modify(TKey key, TValue val)
{
var nk = ManagedToNativeAllocRef(key);
var nv = ManagedToNativeAlloc(val);
var gchnk = CopyNativeObject<TKey>(key, ForceRefKey<TKey>());
var nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
var gchnv = CopyNativeObject<TValue>(val, false);
var nv = GetNativePtr<TValue>(gchnv, false);
var old = eina_hash_modify(Handle, nk, nv);
NativeFreeRef<TKey>(nk);
FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
// NativeFreeRef<TKey>(nk);
if (old == IntPtr.Zero)
{
NativeFree<TValue>(nv);
@ -323,14 +339,82 @@ public class Hash<TKey, TValue> : IEnumerable<KeyValuePair<TKey,TValue>>, IDi
return true;
}
private static bool ForceRefKey<T>()
{
return (!typeof(T).IsValueType) && (typeof(T) != typeof(string));
}
private static IntPtr CopyNativeObject<T>(T value, bool forceRef)
{
if (!IsEflObject(typeof(T)) && forceRef)
{
GCHandle gch = GCHandle.Alloc(new byte[Marshal.SizeOf<T>()], GCHandleType.Pinned);
IntPtr pin = gch.AddrOfPinnedObject();
ManagedToNativeCopyTo(value, pin);
return GCHandle.ToIntPtr(gch);
}
else if(IsEflObject(typeof(T)) && forceRef)
{
GCHandle gch = GCHandle.Alloc(new byte[Marshal.SizeOf<IntPtr>()], GCHandleType.Pinned);
IntPtr pin = gch.AddrOfPinnedObject();
ManagedToNativeCopyTo(value, pin);
return GCHandle.ToIntPtr(gch);
}
else
{
return ManagedToNativeAlloc(value);
}
}
private static IntPtr GetNativePtr<T>(IntPtr gchptr, bool forceRef)
{
if (forceRef)
{
GCHandle gch = GCHandle.FromIntPtr(gchptr);
IntPtr pin = gch.AddrOfPinnedObject();
return pin;
}
else
{
return gchptr;
}
}
private static void FreeNativeIndirection<T>(IntPtr gchptr, bool forceRef)
{
if (forceRef)
{
GCHandle gch = GCHandle.FromIntPtr(gchptr);
gch.Free();
}
}
private static IntPtr IndirectNative<T>(IntPtr ptr, bool forceRef)
{
if (forceRef)
{
IntPtr val = Marshal.ReadIntPtr(ptr);
return val;
}
else
{
return ptr;
}
}
public void Set(TKey key, TValue val)
{
var nk = ManagedToNativeAllocRef(key, true);
var nv = ManagedToNativeAlloc(val);
var old = eina_hash_set(Handle, nk, nv);
NativeFreeRef<TKey>(nk, old != IntPtr.Zero);
if (old != IntPtr.Zero && OwnValue)
NativeFree<TValue>(old);
IntPtr gchnk = CopyNativeObject(key, ForceRefKey<TKey>());
IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
IntPtr gchnv = CopyNativeObject(val, false);
IntPtr nv = GetNativePtr<TValue>(gchnv, false);
IntPtr old = eina_hash_set(Handle, nk, nv);
FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
FreeNativeIndirection<TValue>(gchnv, false);
}
public TValue this[TKey key]
@ -347,11 +431,17 @@ public class Hash<TKey, TValue> : IEnumerable<KeyValuePair<TKey,TValue>>, IDi
public bool Move(TKey key_old, TKey key_new)
{
var nk_old = ManagedToNativeAllocRef(key_old);
var nk_new = ManagedToNativeAllocRef(key_new, true);
var r = eina_hash_move(Handle, nk_old, nk_new);
NativeFreeRef<TKey>(nk_old, OwnKey && r);
NativeFreeRef<TKey>(nk_new, !r);
IntPtr gchnko = CopyNativeObject(key_old, ForceRefKey<TKey>());
IntPtr nko = GetNativePtr<TKey>(gchnko, ForceRefKey<TKey>());
IntPtr gchnk = CopyNativeObject(key_new, ForceRefKey<TKey>());
IntPtr nk = GetNativePtr<TKey>(gchnk, ForceRefKey<TKey>());
// var nk_old = ManagedToNativeAllocRef(key_old);
// var nk_new = ManagedToNativeAllocRef(key_new, true);
var r = eina_hash_move(Handle, nko, nk);
FreeNativeIndirection<TKey>(gchnko, ForceRefKey<TKey>());
FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
// NativeFreeRef<TKey>(nk_old, OwnKey && r);
// NativeFreeRef<TKey>(nk_new, !r);
return r;
}
@ -383,7 +473,8 @@ public class Hash<TKey, TValue> : IEnumerable<KeyValuePair<TKey,TValue>>, IDi
for (IntPtr tuplePtr; eina_iterator_next(itr, out tuplePtr);)
{
var tuple = Marshal.PtrToStructure<Eina.HashTupleNative>(tuplePtr);
var key = NativeToManagedRef<TKey>(tuple.key);
IntPtr ikey = IndirectNative<TKey>(tuple.key, ForceRefKey<TKey>());
var key = NativeToManaged<TKey>(ikey);
var val = NativeToManaged<TValue>(tuple.data);
yield return new KeyValuePair<TKey, TValue>(key, val);
}

View File

@ -193,11 +193,17 @@ public class Inarray<T> : IEnumerable<T>, IDisposable
public int Push(T val)
{
IntPtr ele = ManagedToNativeAllocInplace(val);
var r = eina_inarray_push(Handle, ele);
IntPtr ele = IntPtr.Zero;
GCHandle gch = GCHandle.Alloc(ele, GCHandleType.Pinned);
IntPtr ind = gch.AddrOfPinnedObject();
ManagedToNativeCopyTo(val, ind);
var r = eina_inarray_push(Handle, ind);
if (r == -1)
NativeFreeInplace<T>(ele);
ResidueFreeInplace<T>(ele);
gch.Free();
return r;
}
@ -220,6 +226,7 @@ public class Inarray<T> : IEnumerable<T>, IDisposable
public T Nth(uint idx)
{
IntPtr ele = eina_inarray_nth(Handle, idx);
IntPtr v = Marshal.ReadIntPtr(ele);
return NativeToManagedInplace<T>(ele);
}
@ -230,8 +237,13 @@ public class Inarray<T> : IEnumerable<T>, IDisposable
public bool InsertAt(uint idx, T val)
{
IntPtr ele = ManagedToNativeAllocInplace(val);
var r = eina_inarray_insert_at(Handle, idx, ele);
IntPtr ele = IntPtr.Zero;
GCHandle gch = GCHandle.Alloc(ele, GCHandleType.Pinned);
IntPtr ind = gch.AddrOfPinnedObject();
ManagedToNativeCopyTo(val, ind);
var r = eina_inarray_insert_at(Handle, idx, ind);
if (!r)
NativeFreeInplace<T>(ele);
ResidueFreeInplace<T>(ele);
@ -245,8 +257,13 @@ public class Inarray<T> : IEnumerable<T>, IDisposable
return false;
if (OwnContent)
NativeFreeInplace<T>(old);
var ele = ManagedToNativeAllocInplace(val);
var r = eina_inarray_replace_at(Handle, idx, ele);
var ele = IntPtr.Zero;
GCHandle gch = GCHandle.Alloc(ele, GCHandleType.Pinned);
IntPtr ind = gch.AddrOfPinnedObject();
ManagedToNativeCopyTo(val, ind);
var r = eina_inarray_replace_at(Handle, idx, ind);
ResidueFreeInplace<T>(ele);
return r;
}

View File

@ -0,0 +1,95 @@
using System;
using System.Runtime.InteropServices;
namespace Efl { namespace Eo {
public partial class FunctionInterop
{
public static IntPtr LoadFunctionPointer(string moduleName, string functionName)
{
NativeModule module = new NativeModule(moduleName);
Eina.Log.Debug($"searching {module.Module} for {functionName}");
var s = FunctionInterop.dlsym(module.Module, functionName);
Eina.Log.Debug($"searching {module.Module} for{functionName}, result {s}");
return s;
}
public static IntPtr LoadFunctionPointer(string functionName)
{
Eina.Log.Debug($"searching {null} for {functionName}");
var s = FunctionInterop.dlsym(IntPtr.Zero, functionName);
Eina.Log.Debug($"searching {null} for {functionName}, result {s}");
return s;
}
}
public class FunctionWrapper<T>
{
private Lazy<FunctionLoadResult<T>> loadResult;
private NativeModule module; // so it doesn't get unloaded
private static FunctionLoadResult<T> LazyInitialization(NativeModule module, string functionName)
{
if (module.Module == IntPtr.Zero)
return new FunctionLoadResult<T>(FunctionLoadResultKind.LibraryNotFound);
else
{
IntPtr funcptr = FunctionInterop.LoadFunctionPointer(module.Module, functionName);
if (funcptr == IntPtr.Zero)
return new FunctionLoadResult<T>(FunctionLoadResultKind.FunctionNotFound);
else
return new FunctionLoadResult<T>(Marshal.GetDelegateForFunctionPointer<T>(funcptr));
}
}
public FunctionWrapper(string moduleName, string functionName)
: this (new NativeModule(moduleName), functionName)
{
}
public FunctionWrapper(NativeModule module, string functionName)
{
this.module = module;
loadResult = new Lazy<FunctionLoadResult<T>>
(() =>
{
return LazyInitialization(module, functionName);
});
}
public FunctionLoadResult<T> Value
{
get
{
return loadResult.Value;
}
}
}
public enum FunctionLoadResultKind { Success, LibraryNotFound, FunctionNotFound }
public class FunctionLoadResult<T>
{
public FunctionLoadResultKind Kind;
public T _Delegate;
public T Delegate
{
get {
if (_Delegate == null)
throw new InvalidOperationException($"Trying to get Delegate while not loaded. Load result: {Kind}");
return _Delegate;
}
}
public FunctionLoadResult(FunctionLoadResultKind kind)
{
this.Kind = kind;
}
public FunctionLoadResult(T Delegate)
{
this._Delegate = Delegate;
this.Kind = FunctionLoadResultKind.Success;
}
}
} }

View File

@ -0,0 +1,21 @@
using System;
using System.Runtime.InteropServices;
namespace Efl { namespace Eo {
public partial class FunctionInterop
{
[DllImport(efl.Libs.Libdl)]
public static extern IntPtr dlsym(IntPtr handle, string symbol);
public static IntPtr LoadFunctionPointer(IntPtr nativeLibraryHandle, string functionName)
{
Eina.Log.Debug("searching {nativeLibraryHandle} for {functionName}");
var s = FunctionInterop.dlsym(nativeLibraryHandle, functionName);
Eina.Log.Debug("searching {nativeLibraryHandle} for {functionName}, result {s}");
return s;
}
}
} }

View File

@ -0,0 +1,15 @@
using System;
using System.Runtime.InteropServices;
namespace Efl { namespace Eo {
public partial class FunctionInterop
{
[DllImport(efl.Libs.Libdl)]
public static extern IntPtr GetProcAddress(IntPtr handle, string symbol);
private static IntPtr LoadFunctionPointer(IntPtr nativeLibraryHandle, string functionName)
=> FunctionInterop.GetProcAddress(nativeLibraryHandle, functionName);
}
} }

View File

@ -0,0 +1,33 @@
using System;
namespace Efl { namespace Eo {
public partial class NativeModule : IDisposable
{
private Lazy<IntPtr> module;
public NativeModule(string libName)
{
module = new Lazy<IntPtr>
(() =>
{
return LoadLibrary(libName);
});
}
public IntPtr Module
{
get
{
return module.Value;
}
}
public void Dispose()
{
UnloadLibrary(module.Value);
module = null;
}
}
} }

View File

@ -0,0 +1,46 @@
using System;
using System.Runtime.InteropServices;
namespace Efl { namespace Eo {
public partial class NativeModule
{
public const int RTLD_NOW = 0x002;
// Currently we are using GLOBAL due to issues
// with the way evas modules are built.
public const int RTLD_GLOBAL = 0x100;
[DllImport(efl.Libs.Libdl)]
public static extern IntPtr dlopen(string fileName, int flag);
[DllImport(efl.Libs.Libdl)]
public static extern int dlclose(IntPtr handle);
public static void UnloadLibrary(IntPtr handle)
{
dlclose(handle);
}
public static IntPtr LoadLibrary(string filename)
{
Eina.Log.Debug($"Loading library {filename}");
var r = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
if (r == IntPtr.Zero)
{
r = dlopen("lib" + filename, RTLD_NOW | RTLD_GLOBAL);
if (r == IntPtr.Zero)
{
r = dlopen(filename + ".so", RTLD_NOW | RTLD_GLOBAL);
if (r == IntPtr.Zero)
{
r = dlopen("lib" + filename + ".so", RTLD_NOW | RTLD_GLOBAL);
}
}
}
return r;
}
}
} }

View File

@ -0,0 +1,15 @@
using System;
using System.Runtime.InteropServices;
namespace Efl { namespace Eo {
public class partial NativeModule
{
[DllImport(efl.Libs.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr LoadLibrary(string libFilename);
}
} }

View File

@ -12,19 +12,40 @@ using EoG = Efl.Eo.Globals;
namespace Efl { namespace Eo {
public class Globals {
[DllImport(efl.Libs.Eo)] public static extern void efl_object_init();
[DllImport(efl.Libs.Eo)] public static extern void efl_object_shutdown();
[return: MarshalAs(UnmanagedType.U1)]
public delegate bool efl_object_init_delegate();
public static FunctionWrapper<efl_object_init_delegate> efl_object_init_ptr =
new FunctionWrapper<efl_object_init_delegate>(efl.Libs.EoModule, "efl_object_init");
public static bool efl_object_init() => efl_object_init_ptr.Value.Delegate();
public delegate void efl_object_shutdown_delegate();
public static FunctionWrapper<efl_object_shutdown_delegate> efl_object_shutdown_ptr = new FunctionWrapper<efl_object_shutdown_delegate>(efl.Libs.EoModule, "efl_object_shutdown");
public static void efl_object_shutdown() => efl_object_shutdown_ptr.Value.Delegate();
// [DllImport(efl.Libs.Eo)] public static extern void efl_object_shutdown();
public static FunctionWrapper<_efl_add_internal_start_delegate> _efl_add_internal_start_ptr = new FunctionWrapper<_efl_add_internal_start_delegate>(efl.Libs.EoModule, "_efl_add_internal_start");
public delegate IntPtr
_efl_add_internal_start_delegate([MarshalAs(UnmanagedType.LPStr)] String file, int line,
IntPtr klass, IntPtr parent, byte is_ref, byte is_fallback);
[DllImport(efl.Libs.Eo)] public static extern IntPtr
_efl_add_internal_start([MarshalAs(UnmanagedType.LPStr)] String file, int line,
IntPtr klass, IntPtr parent, byte is_ref, byte is_fallback);
public delegate IntPtr
_efl_add_end_delegate(IntPtr eo, byte is_ref, byte is_fallback);
[DllImport(efl.Libs.Eo)] public static extern IntPtr
_efl_add_end(IntPtr eo, byte is_ref, byte is_fallback);
public delegate IntPtr
efl_ref_delegate(IntPtr eo);
[DllImport(efl.Libs.Eo)] public static extern IntPtr
efl_ref(IntPtr eo);
public delegate void
efl_unref_delegate(IntPtr eo);
[DllImport(efl.Libs.CustomExports)] public static extern void
efl_unref(IntPtr eo);
public delegate int
efl_ref_count_delegate(IntPtr eo);
[DllImport(efl.Libs.Eo)] public static extern int
efl_ref_count(IntPtr eo);
[DllImport(efl.Libs.Eo)] public static extern IntPtr
efl_class_name_get(IntPtr eo);
[DllImport(efl.Libs.Eo)] public static extern IntPtr
@ -125,30 +146,42 @@ public class Globals {
efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr extn38, IntPtr extn39, IntPtr extn40, IntPtr extn41, IntPtr extn42, IntPtr extn43, IntPtr extn44, IntPtr extn45, IntPtr extn46, IntPtr extn47, IntPtr term);
[DllImport(efl.Libs.Eo)] public static extern IntPtr
efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr extn38, IntPtr extn39, IntPtr extn40, IntPtr extn41, IntPtr extn42, IntPtr extn43, IntPtr extn44, IntPtr extn45, IntPtr extn46, IntPtr extn47, IntPtr extn48, IntPtr term);
[DllImport(efl.Libs.Eo)] public static extern byte efl_class_functions_set(IntPtr klass_id, IntPtr object_ops, IntPtr class_ops, IntPtr reflection_ops);
[DllImport(efl.Libs.Eo)] public static extern IntPtr efl_data_scope_get(IntPtr obj, IntPtr klass);
[DllImport(efl.Libs.Eo)] public static extern IntPtr efl_super(IntPtr obj, IntPtr klass);
[DllImport(efl.Libs.Eo)] public static extern IntPtr efl_class_get(IntPtr obj);
#if WIN32
public static IntPtr RTLD_DEFAULT = new IntPtr(1);
#else
public static IntPtr RTLD_DEFAULT = new IntPtr(0);
#endif
[DllImport(efl.Libs.Evil)] public static extern IntPtr dlerror();
[DllImport(efl.Libs.Evil)] public static extern IntPtr dlsym
(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)] String name);
[DllImport(efl.Libs.Eo)] public static extern bool efl_event_callback_priority_add(
public delegate byte efl_class_functions_set_delegate(IntPtr klass_id, IntPtr object_ops, IntPtr class_ops);
[DllImport(efl.Libs.Eo)] public static extern byte efl_class_functions_set(IntPtr klass_id, IntPtr object_ops, IntPtr class_ops);
public delegate IntPtr efl_data_scope_get_delegate(IntPtr obj, IntPtr klass);
[DllImport(efl.Libs.Eo)] public static extern IntPtr efl_data_scope_get(IntPtr obj, IntPtr klass);
public delegate IntPtr efl_super_delegate(IntPtr obj, IntPtr klass);
[DllImport(efl.Libs.Eo)] public static extern IntPtr efl_super(IntPtr obj, IntPtr klass);
public delegate IntPtr efl_class_get_delegate(IntPtr obj);
[DllImport(efl.Libs.Eo)] public static extern IntPtr efl_class_get(IntPtr obj);
public delegate IntPtr dlerror_delegate();
[DllImport(efl.Libs.Evil)] public static extern IntPtr dlerror();
public delegate bool efl_event_callback_priority_add_delegate(
System.IntPtr obj,
IntPtr desc,
short priority,
Efl.EventCb cb,
System.IntPtr data);
[DllImport(efl.Libs.Eo)] public static extern bool efl_event_callback_del(
[DllImport(efl.Libs.Eo)] public static extern bool efl_event_callback_priority_add(
System.IntPtr obj,
IntPtr desc,
short priority,
Efl.EventCb cb,
System.IntPtr data);
public delegate bool efl_event_callback_del_delegate(
System.IntPtr obj,
IntPtr desc,
Efl.EventCb cb,
System.IntPtr data);
[DllImport(efl.Libs.Eo)] public static extern bool efl_event_callback_del(
System.IntPtr obj,
IntPtr desc,
Efl.EventCb cb,
System.IntPtr data);
public delegate IntPtr
efl_object_legacy_only_event_description_get_delegate([MarshalAs(UnmanagedType.LPStr)] String name);
[DllImport(efl.Libs.Eo)] public static extern IntPtr
efl_object_legacy_only_event_description_get([MarshalAs(UnmanagedType.LPStr)] String name);
@ -240,7 +273,7 @@ public class Globals {
}
public static byte class_initializer_call(IntPtr klass, System.Type type)
{
Eina.Log.Debug($"called with 0x{klass.ToInt64()} {type}");
Eina.Log.Debug($"called with 0x{klass.ToInt64():x} {type}");
Efl.Eo.NativeClass nativeClass = get_native_class(type.BaseType);
if (nativeClass != null)
@ -259,7 +292,7 @@ public class Globals {
if(nc != null)
{
var moredescs = nc.GetEoOps(type);
Eina.Log.Debug("adding {moredescs.Count} more descs to registration");
Eina.Log.Debug($"adding {moredescs.Count} more descs to registration");
descs.AddRange(moredescs);
count = descs.Count;
}
@ -278,7 +311,7 @@ public class Globals {
ops.count = (UIntPtr)count;
IntPtr ops_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ops));
Marshal.StructureToPtr(ops, ops_ptr, false);
Efl.Eo.Globals.efl_class_functions_set(klass, ops_ptr, IntPtr.Zero, IntPtr.Zero);
Efl.Eo.Globals.efl_class_functions_set(klass, ops_ptr, IntPtr.Zero);
//EoKlass = klass;
}
else
@ -391,38 +424,6 @@ public class Globals {
return null;
}
public static IntPtr cached_string_to_intptr(Dictionary<String, IntPtr> dict, String str)
{
IntPtr ptr = IntPtr.Zero;
if (str == null)
return ptr;
if (!dict.TryGetValue(str, out ptr))
{
ptr = Eina.StringConversion.ManagedStringToNativeUtf8Alloc(str);
dict[str] = ptr;
}
return ptr;
}
public static IntPtr cached_stringshare_to_intptr(Dictionary<String, IntPtr> dict, String str)
{
IntPtr ptr = IntPtr.Zero;
if (str == null)
return ptr;
if (!dict.TryGetValue(str, out ptr))
{
ptr = Eina.Stringshare.eina_stringshare_add(str);
dict[str] = ptr;
}
return ptr;
}
public static void free_dict_values(Dictionary<String, IntPtr> dict)
{
foreach(IntPtr ptr in dict.Values)

View File

@ -1,4 +1,12 @@
mono_files += files(
'iwrapper.cs',
'workaround.cs'
'workaround.cs',
'FunctionWrapper.cs',
'NativeModule.cs'
)
if host_machine.system() == 'windows'
mono_files += files('FunctionWrapper_Windows.cs', 'NativeModule_Windows.cs')
else
mono_files += files('FunctionWrapper_Unix.cs', 'NativeModule_Unix.cs')
endif

View File

@ -80,19 +80,19 @@ public struct EventDescription {
private static Dictionary<string, IntPtr> descriptions = new Dictionary<string, IntPtr>();
public EventDescription(string name)
public EventDescription(string module, string name)
{
this.Name = GetNative(name);
this.Name = GetNative(module, name);
this.Unfreezable = false;
this.Legacy_is = false;
this.Restart = false;
}
public static IntPtr GetNative(string name)
public static IntPtr GetNative(string module, string name)
{
if (!descriptions.ContainsKey(name))
{
IntPtr data = Efl.Eo.Globals.dlsym(Efl.Eo.Globals.RTLD_DEFAULT, name);
IntPtr data = Efl.Eo.FunctionInterop.LoadFunctionPointer(module, name);
if (data == IntPtr.Zero) {
string error = Eina.StringConversion.NativeUtf8ToManagedString(Efl.Eo.Globals.dlerror());

View File

@ -1,5 +1,31 @@
add_languages('cs')
runtime_assemblies = []
# Check if we should use dotnet options
cs_is_dotnet = meson.get_compiler('cs').get_id().contains('dotnet')
if (cs_is_dotnet)
runtime_assemblies += [
'System.Console',
'Microsoft.CSharp',
'System.Collections',
'System.Collections.Concurrent',
'System.ComponentModel.Primitives',
'System.ComponentModel.Primitives',
'System.Diagnostics.Debug',
'System.Diagnostics.TraceSource',
'System.Dynamic.Runtime',
'System.Linq',
'System.Runtime',
'System.Runtime.Extensions',
'System.Security',
]
endif
mono_sublibs = [
['Eina', true, ], #
['Eolian', true, ], #
@ -114,15 +140,24 @@ efl_mono_conf_data.set('EVAS', evas_lib.full_path())
efl_mono_conf_data.set('ELDBUS', eldbus_lib.full_path())
efl_mono_conf_data.set('ELEMENTARY', elementary_lib.full_path())
configure_file(input : 'efl_mono.dll.config.in',
output : 'efl_mono.dll.config',
configuration : efl_mono_conf_data)
efl_mono_dll_config = configure_file(input : 'efl_mono.dll.config.in',
output : 'efl_mono.dll.config',
configuration : efl_mono_conf_data)
if (cs_is_dotnet)
efl_mono = library('efl_mono',
mono_generator_target + mono_files + [efl_src],
install : true,
install_dir : join_paths(dir_lib, 'efl-mono-'+version_major)
install_dir : join_paths(dir_lib, 'efl-mono-'+version_major),
runtime_assemblies : runtime_assemblies
)
else
efl_mono = library('efl_mono',
mono_generator_target + mono_files + [efl_src],
install : true,
install_dir : join_paths(dir_lib, 'efl-mono-'+version_major),
)
endif
efl_mono_test_suite_path=join_paths(meson.current_build_dir())

View File

@ -16,6 +16,8 @@
#include <vector>
#include <memory>
#include <set>
#include <iosfwd>
#include <string>
namespace efl { namespace eolian { namespace grammar {
@ -73,6 +75,26 @@ enum class typedecl_type
function_ptr,
};
inline std::ostream& operator<<(std::ostream& s, typedecl_type dec)
{
switch(dec)
{
case typedecl_type::unknown:
return s << "unknown";
case typedecl_type::struct_:
return s << "struct_";
case typedecl_type::struct_opaque:
return s << "struct_opaque";
case typedecl_type::enum_:
return s << "enum_";
case typedecl_type::alias:
return s << "alias";
case typedecl_type::function_ptr:
return s << "function_ptr";
};
return s;
}
inline typedecl_type typedecl_type_get(Eolian_Typedecl const* decl)
{
if (!decl)
@ -108,6 +130,22 @@ enum class class_type
regular, abstract_, mixin, interface_
};
inline std::ostream& operator<<(std::ostream& s, class_type t)
{
switch(t)
{
case class_type::regular:
return s << "regular";
case class_type::abstract_:
return s << "abstract_";
case class_type::mixin:
return s << "mixin";
case class_type::interface_:
return s << "interface_";
};
return s;
}
struct klass_name
{
std::vector<std::string> namespaces;
@ -116,6 +154,14 @@ struct klass_name
class_type type;
std::string klass_get_name;
friend inline std::ostream& operator<<(std::ostream& s, klass_name const& name)
{
s << "[ namespaces: {";
std::copy(name.namespaces.begin(), name.namespaces.end(), std::ostream_iterator<std::string>(s, ","));
return s << "}, eolian_name: " << name.eolian_name << " base_qualifier: " << name.base_qualifier
<< " type: " << name.type << " klass_get_name: " << name.klass_get_name << "]";
}
klass_name() {
}
@ -272,6 +318,14 @@ struct regular_type_def
bool is_alias() const { return is_type(typedecl_type::alias); }
bool is_function_ptr() const { return is_type(typedecl_type::function_ptr); }
friend inline std::ostream& operator<<(std::ostream& s, regular_type_def const& def)
{
s << "[ base_type: " << def.base_type << " base_qualifier: " << def.base_qualifier
<< " namespaces: ";
std::copy(def.namespaces.begin(), def.namespaces.end(), std::ostream_iterator<std::string>(s, ", "));
return s << " type_type: " << def.type_type << " is_undefined " << def.is_undefined << "]";
}
std::string base_type;
qualifier_def base_qualifier;
std::vector<std::string> namespaces;
@ -292,6 +346,13 @@ struct complex_type_def
{
regular_type_def outer;
std::vector<type_def> subtypes;
friend inline std::ostream& operator<<(std::ostream& s, complex_type_def const& def)
{
s << "[ outer " << def.outer << " subtypes: {";
std::copy(def.subtypes.begin(), def.subtypes.end(), std::ostream_iterator<type_def>(s, ", "));
return s << "}]";
}
};
inline bool operator==(complex_type_def const& lhs, complex_type_def const& rhs)
@ -326,6 +387,12 @@ struct type_def
{
return lhs.c_type < rhs.c_type;
}
friend inline std::ostream& operator<<(std::ostream& s, type_def const& rhs)
{
return s << "[ original: " << rhs.original_type << " c_type "
<< rhs.c_type << " has_own " << rhs.has_own << " is_ptr "
<< rhs.is_ptr << "]";
}
};
struct get_qualifier_visitor

View File

@ -10,6 +10,13 @@ class TestEo
{
}
public static void return_null_object()
{
var testing = new Dummy.TestObject();
var o1 = testing.ReturnNullObject();
Test.Assert(o1 == null);
}
//
// Test cases:
//

View File

@ -112,6 +112,10 @@ class Dummy.Test_Object extends Efl.Object implements Efl.Part, Dummy.Test_Iface
return: Dummy.Test_Object;
}
return_null_object {
return: Dummy.Test_Object;
}
int_out {
params {
@in x: int;

View File

@ -0,0 +1,10 @@
{
"runtimeOptions": {
"tfm": "netcoreapp2.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "2.0.0"
}
}
}

View File

@ -162,6 +162,11 @@ Efl_Object *_dummy_test_object_return_object(Eo *obj, EINA_UNUSED Dummy_Test_Obj
return obj;
}
Efl_Object *_dummy_test_object_return_null_object(Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
return NULL;
}
void _dummy_test_object_int_out(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, int x, int *y)
{
*y = -x;

View File

@ -31,10 +31,18 @@ foreach mono_gen_file : eo_files
'@INPUT@'])
endforeach
if (cs_is_dotnet)
efl_mono_test = library('efl_mono_test',
eo_file_targets,
link_with : [efl_mono],
runtime_assemblies : runtime_assemblies
)
else
efl_mono_test = library('efl_mono_test',
eo_file_targets,
link_with : [efl_mono],
)
endif
efl_mono_src = [
'Main.cs',
@ -60,14 +68,43 @@ efl_mono_src = [
'Inheritance.cs',
]
if (cs_is_dotnet)
efl_mono_suite = executable('efl-mono-suite',
efl_mono_src,
link_with : [efl_mono, efl_mono_test],
runtime_assemblies : runtime_assemblies
)
else
efl_mono_suite = executable('efl-mono-suite',
efl_mono_src,
link_with : [efl_mono, efl_mono_test],
)
endif
env = environment()
env.set('MONO_PATH', efl_mono_test_suite_path )
if (cs_is_dotnet)
env.set('LD_LIBRARY_PATH', efl_mono_test_suite_path )
copy_prog = find_program(['cp', 'copy'])
configure_file(input : 'efl-mono-suite.runtimeconfig.json',
output : 'efl-mono-suite.runtimeconfig.json',
copy : true)
custom_target('copy_efl_mono_dll',
build_by_default : true,
input : efl_mono,
output : efl_mono.full_path().split('/')[-1],
command : [copy_prog, '@INPUT@', '@OUTPUT@'])
custom_target('copy_efl_mono_lib_dll',
build_by_default : true,
input : efl_mono_lib,
output : efl_mono_lib.full_path().split('/')[-1],
command : [copy_prog, '@INPUT@', '@OUTPUT@'])
endif
config_libs = ['eina', 'ecore', 'eo', 'efl', 'evas', 'eldbus', 'elementary']
load_lib = ''