forked from enlightenment/efl
csharp: Update string marshalers
Mostly done, needs work on strings being returned without ownership from C# to C.
This commit is contained in:
parent
52da69510f
commit
c1293edbd2
|
@ -51,23 +51,22 @@ struct marshall_annotation_visitor_generate
|
||||||
eina::optional<bool> has_own;
|
eina::optional<bool> has_own;
|
||||||
std::function<std::string()> function;
|
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 input_match_table[] =
|
||||||
match const parameter_match_table[] =
|
|
||||||
{
|
{
|
||||||
// signed primitives
|
// signed primitives
|
||||||
{"bool", nullptr, [] { return "MarshalAs(UnmanagedType.U1)"; }},
|
{"bool", nullptr, [] { return "MarshalAs(UnmanagedType.U1)"; }},
|
||||||
{"string", true, [] {
|
{"string", true, [] {
|
||||||
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))";
|
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringInPassOwnershipMarshaler))";
|
||||||
}},
|
}},
|
||||||
{"string", false, [] {
|
{"string", false, [] {
|
||||||
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))";
|
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringInKeepOwnershipMarshaler))";
|
||||||
}},
|
}},
|
||||||
{"mstring", true, [] {
|
{"mstring", true, [] {
|
||||||
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))";
|
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringInPassOwnershipMarshaler))";
|
||||||
}},
|
}},
|
||||||
{"mstring", false, [] {
|
{"mstring", false, [] {
|
||||||
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))";
|
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringInKeepOwnershipMarshaler))";
|
||||||
}},
|
}},
|
||||||
{"stringshare", true, [] {
|
{"stringshare", true, [] {
|
||||||
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringsharePassOwnershipMarshaler))";
|
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringsharePassOwnershipMarshaler))";
|
||||||
|
@ -96,16 +95,16 @@ struct marshall_annotation_visitor_generate
|
||||||
// signed primitives
|
// signed primitives
|
||||||
{"bool", nullptr, [] { return "MarshalAs(UnmanagedType.U1)"; }},
|
{"bool", nullptr, [] { return "MarshalAs(UnmanagedType.U1)"; }},
|
||||||
{"string", true, [] {
|
{"string", true, [] {
|
||||||
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))";
|
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringOutPassOwnershipMarshaler))";
|
||||||
}},
|
}},
|
||||||
{"string", false, [] {
|
{"string", false, [] {
|
||||||
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))";
|
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringOutKeepOwnershipMarshaler))";
|
||||||
}},
|
}},
|
||||||
{"mstring", true, [] {
|
{"mstring", true, [] {
|
||||||
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))";
|
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringOutPassOwnershipMarshaler))";
|
||||||
}},
|
}},
|
||||||
{"mstring", false, [] {
|
{"mstring", false, [] {
|
||||||
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))";
|
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringOutKeepOwnershipMarshaler))";
|
||||||
}},
|
}},
|
||||||
{"stringshare", true, [] {
|
{"stringshare", true, [] {
|
||||||
return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringsharePassOwnershipMarshaler))";
|
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);
|
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))
|
if(eina::optional<bool> b = type_match::get_match(match_table, predicate, acceptCb))
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,7 +43,7 @@ internal static class Environment
|
||||||
internal static partial class NativeCustomExportFunctions
|
internal static partial class NativeCustomExportFunctions
|
||||||
{
|
{
|
||||||
[DllImport(efl.Libs.CustomExports, CharSet=CharSet.Ansi)]
|
[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);
|
public static extern string efl_mono_native_getenv(string name);
|
||||||
|
|
||||||
[DllImport(efl.Libs.CustomExports, CharSet=CharSet.Ansi)]
|
[DllImport(efl.Libs.CustomExports, CharSet=CharSet.Ansi)]
|
||||||
|
|
|
@ -51,13 +51,13 @@ static internal class StrbufNativeMethods
|
||||||
[DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)]
|
[DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)]
|
||||||
[return:
|
[return:
|
||||||
MarshalAs(UnmanagedType.CustomMarshaler,
|
MarshalAs(UnmanagedType.CustomMarshaler,
|
||||||
MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))]
|
MarshalTypeRef=typeof(Efl.Eo.StringOutPassOwnershipMarshaler))]
|
||||||
internal static extern string eina_strbuf_string_steal(IntPtr buf);
|
internal static extern string eina_strbuf_string_steal(IntPtr buf);
|
||||||
|
|
||||||
[DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)]
|
[DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)]
|
||||||
[return:
|
[return:
|
||||||
MarshalAs(UnmanagedType.CustomMarshaler,
|
MarshalAs(UnmanagedType.CustomMarshaler,
|
||||||
MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))]
|
MarshalTypeRef=typeof(Efl.Eo.StringOutKeepOwnershipMarshaler))]
|
||||||
internal static extern string eina_strbuf_string_get(IntPtr buf);
|
internal static extern string eina_strbuf_string_get(IntPtr buf);
|
||||||
|
|
||||||
[DllImport(efl.Libs.Eina)]
|
[DllImport(efl.Libs.Eina)]
|
||||||
|
|
|
@ -194,7 +194,7 @@ static internal class UnsafeNativeMethods
|
||||||
[DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)]
|
[DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)]
|
||||||
[return:
|
[return:
|
||||||
MarshalAs(UnmanagedType.CustomMarshaler,
|
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.
|
internal static extern string eina_value_to_string(IntPtr handle); // We take ownership of the returned string.
|
||||||
|
|
||||||
[DllImport(efl.Libs.CustomExports)]
|
[DllImport(efl.Libs.CustomExports)]
|
||||||
|
|
|
@ -5,8 +5,12 @@ namespace Efl
|
||||||
{
|
{
|
||||||
namespace Eo
|
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)
|
public object MarshalNativeToManaged(IntPtr pNativeData)
|
||||||
{
|
{
|
||||||
var ret = Eina.StringConversion.NativeUtf8ToManagedString(pNativeData);
|
var ret = Eina.StringConversion.NativeUtf8ToManagedString(pNativeData);
|
||||||
|
@ -14,16 +18,18 @@ namespace Efl
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called when C# calls a C method passing data to it
|
||||||
public IntPtr MarshalManagedToNative(object managedObj)
|
public IntPtr MarshalManagedToNative(object managedObj)
|
||||||
{
|
{
|
||||||
return Eina.MemoryNative.StrDup((string)managedObj);
|
return Eina.MemoryNative.StrDup((string)managedObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called when the C call returns, cleaning the result from MarshalManagedToNative
|
||||||
public void CleanUpNativeData(IntPtr pNativeData)
|
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)
|
public void CleanUpManagedData(object managedObj)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -37,32 +43,86 @@ namespace Efl
|
||||||
{
|
{
|
||||||
if (marshaler == null)
|
if (marshaler == null)
|
||||||
{
|
{
|
||||||
marshaler = new StringPassOwnershipMarshaler();
|
marshaler = new StringInPassOwnershipMarshaler();
|
||||||
}
|
}
|
||||||
|
|
||||||
return marshaler;
|
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)
|
public object MarshalNativeToManaged(IntPtr pNativeData)
|
||||||
{
|
{
|
||||||
return Eina.StringConversion.NativeUtf8ToManagedString(pNativeData);
|
return Eina.StringConversion.NativeUtf8ToManagedString(pNativeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called when C# calls a C method passing data to it
|
||||||
public IntPtr MarshalManagedToNative(object managedObj)
|
public IntPtr MarshalManagedToNative(object managedObj)
|
||||||
{
|
{
|
||||||
return Eina.StringConversion.ManagedStringToNativeUtf8Alloc((string)managedObj);
|
return Eina.StringConversion.ManagedStringToNativeUtf8Alloc((string)managedObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called when the C call returns, cleaning the result from MarshalManagedToNative
|
||||||
public void CleanUpNativeData(IntPtr pNativeData)
|
public void CleanUpNativeData(IntPtr pNativeData)
|
||||||
{
|
{
|
||||||
// No need to free. The Native side will keep the ownership.
|
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 void CleanUpManagedData(object managedObj)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -76,13 +136,57 @@ namespace Efl
|
||||||
{
|
{
|
||||||
if (marshaler == null)
|
if (marshaler == null)
|
||||||
{
|
{
|
||||||
marshaler = new StringKeepOwnershipMarshaler();
|
marshaler = new StringOutPassOwnershipMarshaler();
|
||||||
}
|
}
|
||||||
|
|
||||||
return marshaler;
|
return marshaler;
|
||||||
}
|
}
|
||||||
|
|
||||||
static private StringKeepOwnershipMarshaler 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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetNativeDataSize()
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ICustomMarshaler GetInstance(string cookie)
|
||||||
|
{
|
||||||
|
if (marshaler == null)
|
||||||
|
{
|
||||||
|
marshaler = new StringOutKeepOwnershipMarshaler();
|
||||||
|
}
|
||||||
|
|
||||||
|
return marshaler;
|
||||||
|
}
|
||||||
|
|
||||||
|
static private ICustomMarshaler marshaler;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue