diff options
author | Lauro Moura <lauromoura@expertisesolutions.com.br> | 2019-12-06 19:25:14 -0300 |
---|---|---|
committer | Lauro Moura <lauromoura@expertisesolutions.com.br> | 2019-12-11 00:20:44 -0300 |
commit | c1293edbd2a8bc85c7bc168c05b333c3b605d4c1 (patch) | |
tree | 3f32f5c602f33b34c7a9ced9fd920859ff305e16 | |
parent | 52da69510fc65af427ca0892971b192247042583 (diff) | |
download | efl-c1293edbd2a8bc85c7bc168c05b333c3b605d4c1.tar.gz |
csharp: Update string marshalers
Mostly done, needs work on strings being returned without ownership from
C# to C.
-rw-r--r-- | src/bin/eolian_mono/eolian/mono/marshall_annotation.hh | 23 | ||||
-rw-r--r-- | src/bindings/mono/eina_mono/eina_environment.cs | 2 | ||||
-rw-r--r-- | src/bindings/mono/eina_mono/eina_strbuf.cs | 4 | ||||
-rw-r--r-- | src/bindings/mono/eina_mono/eina_value.cs | 2 | ||||
-rw-r--r-- | src/bindings/mono/eo_mono/StringMarshalers.cs | 118 |
5 files changed, 126 insertions, 23 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh b/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh index a9fc45d7da..3cd9f6d267 100644 --- a/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh +++ b/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh @@ -51,23 +51,22 @@ struct marshall_annotation_visitor_generate eina::optional<bool> has_own; std::function<std::string()> function; }; - // These two tables are currently the same but will hold different marshallers - // for @in and @out/return semantics in a future commit. - match const parameter_match_table[] = + + match const input_match_table[] = { // signed primitives {"bool", nullptr, [] { return "MarshalAs(UnmanagedType.U1)"; }}, {"string", true, [] { - return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))"; + return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringInPassOwnershipMarshaler))"; }}, {"string", false, [] { - return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))"; + return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringInKeepOwnershipMarshaler))"; }}, {"mstring", true, [] { - return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))"; + return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringInPassOwnershipMarshaler))"; }}, {"mstring", false, [] { - return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))"; + return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringInKeepOwnershipMarshaler))"; }}, {"stringshare", true, [] { return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringsharePassOwnershipMarshaler))"; @@ -96,16 +95,16 @@ struct marshall_annotation_visitor_generate // signed primitives {"bool", nullptr, [] { return "MarshalAs(UnmanagedType.U1)"; }}, {"string", true, [] { - return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))"; + return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringOutPassOwnershipMarshaler))"; }}, {"string", false, [] { - return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))"; + return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringOutKeepOwnershipMarshaler))"; }}, {"mstring", true, [] { - return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))"; + return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringOutPassOwnershipMarshaler))"; }}, {"mstring", false, [] { - return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))"; + return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringOutKeepOwnershipMarshaler))"; }}, {"stringshare", true, [] { return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringsharePassOwnershipMarshaler))"; @@ -143,7 +142,7 @@ struct marshall_annotation_visitor_generate return as_generator("[" << prefix << marshalTag << "]").generate(sink, nullptr, *context); }; - const auto& match_table = is_return ? return_match_table : parameter_match_table; + const auto& match_table = (is_return || is_out) ? return_match_table : input_match_table; if(eina::optional<bool> b = type_match::get_match(match_table, predicate, acceptCb)) { diff --git a/src/bindings/mono/eina_mono/eina_environment.cs b/src/bindings/mono/eina_mono/eina_environment.cs index 7cef31cbf1..a06417ca5a 100644 --- a/src/bindings/mono/eina_mono/eina_environment.cs +++ b/src/bindings/mono/eina_mono/eina_environment.cs @@ -43,7 +43,7 @@ internal static class Environment internal static partial class NativeCustomExportFunctions { [DllImport(efl.Libs.CustomExports, CharSet=CharSet.Ansi)] - [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringOutKeepOwnershipMarshaler))] public static extern string efl_mono_native_getenv(string name); [DllImport(efl.Libs.CustomExports, CharSet=CharSet.Ansi)] diff --git a/src/bindings/mono/eina_mono/eina_strbuf.cs b/src/bindings/mono/eina_mono/eina_strbuf.cs index bdde9a911e..b29ffb3033 100644 --- a/src/bindings/mono/eina_mono/eina_strbuf.cs +++ b/src/bindings/mono/eina_mono/eina_strbuf.cs @@ -51,13 +51,13 @@ static internal class StrbufNativeMethods [DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)] [return: MarshalAs(UnmanagedType.CustomMarshaler, - MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))] + MarshalTypeRef=typeof(Efl.Eo.StringOutPassOwnershipMarshaler))] internal static extern string eina_strbuf_string_steal(IntPtr buf); [DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)] [return: MarshalAs(UnmanagedType.CustomMarshaler, - MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))] + MarshalTypeRef=typeof(Efl.Eo.StringOutKeepOwnershipMarshaler))] internal static extern string eina_strbuf_string_get(IntPtr buf); [DllImport(efl.Libs.Eina)] diff --git a/src/bindings/mono/eina_mono/eina_value.cs b/src/bindings/mono/eina_mono/eina_value.cs index 2a2508e08b..728bd64fcc 100644 --- a/src/bindings/mono/eina_mono/eina_value.cs +++ b/src/bindings/mono/eina_mono/eina_value.cs @@ -194,7 +194,7 @@ static internal class UnsafeNativeMethods [DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)] [return: MarshalAs(UnmanagedType.CustomMarshaler, - MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))] + MarshalTypeRef=typeof(Efl.Eo.StringOutPassOwnershipMarshaler))] internal static extern string eina_value_to_string(IntPtr handle); // We take ownership of the returned string. [DllImport(efl.Libs.CustomExports)] diff --git a/src/bindings/mono/eo_mono/StringMarshalers.cs b/src/bindings/mono/eo_mono/StringMarshalers.cs index 39188c138b..7851ed947b 100644 --- a/src/bindings/mono/eo_mono/StringMarshalers.cs +++ b/src/bindings/mono/eo_mono/StringMarshalers.cs @@ -5,8 +5,12 @@ namespace Efl { namespace Eo { - class StringPassOwnershipMarshaler : ICustomMarshaler + /// <summary> + /// Marshaler for <c>@in</c> parameters that have their ownership transfered. + /// </summary> + class StringInPassOwnershipMarshaler : ICustomMarshaler { + // Called when C calls a C# method passing data to it public object MarshalNativeToManaged(IntPtr pNativeData) { var ret = Eina.StringConversion.NativeUtf8ToManagedString(pNativeData); @@ -14,16 +18,18 @@ namespace Efl return ret; } + // Called when C# calls a C method passing data to it public IntPtr MarshalManagedToNative(object managedObj) { return Eina.MemoryNative.StrDup((string)managedObj); } + // Called when the C call returns, cleaning the result from MarshalManagedToNative public void CleanUpNativeData(IntPtr pNativeData) { - // No need to cleanup. C will take care of it. } + // Called when the C# call returns, cleaning the result from MarshalNativeToManaged public void CleanUpManagedData(object managedObj) { } @@ -37,32 +43,130 @@ namespace Efl { if (marshaler == null) { - marshaler = new StringPassOwnershipMarshaler(); + marshaler = new StringInPassOwnershipMarshaler(); } return marshaler; } - static private StringPassOwnershipMarshaler marshaler; + static private ICustomMarshaler marshaler; } - class StringKeepOwnershipMarshaler: ICustomMarshaler + /// <summary> + /// Marshaler for <c>@in</c> parameters that do not change their ownership. + /// </summary> + class StringInKeepOwnershipMarshaler: ICustomMarshaler { + // Called when C calls a C# method passing data to it public object MarshalNativeToManaged(IntPtr pNativeData) { return Eina.StringConversion.NativeUtf8ToManagedString(pNativeData); } + // Called when C# calls a C method passing data to it public IntPtr MarshalManagedToNative(object managedObj) { return Eina.StringConversion.ManagedStringToNativeUtf8Alloc((string)managedObj); } + // Called when the C call returns, cleaning the result from MarshalManagedToNative + public void CleanUpNativeData(IntPtr pNativeData) + { + Eina.MemoryNative.Free(pNativeData); + } + + // Called when the C# call returns, cleaning the result from MarshalNativeToManaged + public void CleanUpManagedData(object managedObj) + { + // GC will should take care of it. + } + + public int GetNativeDataSize() + { + return -1; + } + + internal static ICustomMarshaler GetInstance(string cookie) + { + if (marshaler == null) + { + marshaler = new StringInKeepOwnershipMarshaler(); + } + + return marshaler; + } + + static private ICustomMarshaler marshaler; + } + + class StringOutPassOwnershipMarshaler : ICustomMarshaler + { + // Called when C# calls a C method and receives data from it + public object MarshalNativeToManaged(IntPtr pNativeData) + { + var ret = Eina.StringConversion.NativeUtf8ToManagedString(pNativeData); + // C gave us ownership. Let's free. + Eina.MemoryNative.Free(pNativeData); + return ret; + } + + // Called when C calls a C# method and receives data from it + public IntPtr MarshalManagedToNative(object managedObj) + { + // As we're passing up the ownership, no need to free it. + return Eina.MemoryNative.StrDup((string)managedObj); + } + + // Called when the C call returns, cleaning the result it gave to C# + public void CleanUpNativeData(IntPtr pNativeData) + { + } + + // Called when the C# call returns, cleaning the result it gave to C. + public void CleanUpManagedData(object managedObj) + { + } + + public int GetNativeDataSize() + { + return -1; + } + + internal static ICustomMarshaler GetInstance(string cookie) + { + if (marshaler == null) + { + marshaler = new StringOutPassOwnershipMarshaler(); + } + + return marshaler; + } + + static private ICustomMarshaler marshaler; + } + + class StringOutKeepOwnershipMarshaler: ICustomMarshaler + { + // Called when C# calls a C method and receives data from it + public object MarshalNativeToManaged(IntPtr pNativeData) + { + return Eina.StringConversion.NativeUtf8ToManagedString(pNativeData); + } + + // Called when C calls a C# method and receives data from it + public IntPtr MarshalManagedToNative(object managedObj) + { + // FIXME This will be the tricky one, as it can leak. + return Eina.StringConversion.ManagedStringToNativeUtf8Alloc((string)managedObj); + } + + // Called when the C call returns, cleaning the result it gave to C# public void CleanUpNativeData(IntPtr pNativeData) { // No need to free. The Native side will keep the ownership. } + // Called when the C call returns, cleaning the result it gave to C# public void CleanUpManagedData(object managedObj) { } @@ -76,13 +180,13 @@ namespace Efl { if (marshaler == null) { - marshaler = new StringKeepOwnershipMarshaler(); + marshaler = new StringOutKeepOwnershipMarshaler(); } return marshaler; } - static private StringKeepOwnershipMarshaler marshaler; + static private ICustomMarshaler marshaler; } } |