Skip to content

Commit

Permalink
Callback support
Browse files Browse the repository at this point in the history
  • Loading branch information
badcel committed Aug 22, 2023
1 parent 0ceb7fe commit 99f7233
Show file tree
Hide file tree
Showing 25 changed files with 251 additions and 47 deletions.
32 changes: 32 additions & 0 deletions src/Generation/Generator/Generator/Internal/OpaqueRecordHandle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Generator.Model;

namespace Generator.Generator.Internal;

internal class OpaqueRecordHandle : Generator<GirModel.Record>
{
private readonly Publisher _publisher;

public OpaqueRecordHandle(Publisher publisher)
{
_publisher = publisher;
}

public void Generate(GirModel.Record obj)
{
if (!obj.Opaque)
return;

if (obj.TypeFunction is null)
return;

var source = Renderer.Internal.OpaqueRecordHandle.Render(obj);
var codeUnit = new CodeUnit(
Project: Namespace.GetCanonicalName(obj.Namespace),
Name: Model.OpaqueRecord.GetInternalBoxedHandle(obj),
Source: source,
IsInternal: true
);

_publisher.Publish(codeUnit);
}
}
34 changes: 26 additions & 8 deletions src/Generation/Generator/Model/OpaqueRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,33 @@

internal static class OpaqueRecord
{
public static string GetBoxedHandle(GirModel.Record record)
=> $"GLib.Internal.BoxedHandle<{Namespace.GetInternalName(record.Namespace)}.{Type.GetName(record)}>";
public static string GetPublicClassName(GirModel.Record record)
=> record.Name;

public static string GetOwnedBoxedHandle(GirModel.Record record)
=> $"GLib.Internal.OwnedBoxedHandle<{Namespace.GetInternalName(record.Namespace)}.{Type.GetName(record)}>";
public static string GetFullyQualifiedPublicClassName(GirModel.Record record)
=> Namespace.GetPublicName(record.Namespace) + "." + GetPublicClassName(record);

public static string GetInitiallyUnownedBoxedHandle(GirModel.Record record)
=> $"GLib.Internal.InitiallyUnownedBoxedHandle<{Namespace.GetInternalName(record.Namespace)}.{Type.GetName(record)}>";
public static string GetFullyQualifiedInternalClassName(GirModel.Record record)
=> Namespace.GetInternalName(record.Namespace) + "." + record.Name;

public static string GetInternalBoxedHandle(GirModel.Record record)
=> $"{Type.GetName(record)}BoxedHandle";

public static string GetInternalOwnedBoxedHandle(GirModel.Record record)
=> $"{Type.GetName(record)}OwnedBoxedHandle";

public static string GetInternalInitiallyUnownedBoxedHandle(GirModel.Record record)
=> $"{Type.GetName(record)}InitiallyUnownedBoxedHandle";

public static string GetFullyQuallifiedInternalBoxedHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetInternalBoxedHandle(record)}";

public static string GetFullyQuallifiedOwnedBoxedHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetInternalOwnedBoxedHandle(record)}";

public static string GetFullyQuallifiedInitiallyUnownedBoxedHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetInternalInitiallyUnownedBoxedHandle(record)}";

public static string GetNullBoxedHandle(GirModel.Record record)
=> $"GLib.Internal.BoxedHandle<{Namespace.GetInternalName(record.Namespace)}.{Type.GetName(record)}>.NullHandle";
public static string GetFullyQuallifiedNullBoxedHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{Type.GetName(record)}BoxedHandle.NullHandle";
}
1 change: 1 addition & 0 deletions src/Generation/Generator/Records.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public static void Generate(IEnumerable<GirModel.Record> records, string path)
{
//Opaque records
new Generator.Internal.OpaqueRecord(publisher),
new Generator.Internal.OpaqueRecordHandle(publisher),
new Generator.Public.OpaqueRecord(publisher),

//Regular records
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public RenderableInstanceParameter Convert(GirModel.InstanceParameter instancePa

return new RenderableInstanceParameter(
Name: Model.InstanceParameter.GetName(instanceParameter),
NullableTypeName: Model.OpaqueRecord.GetBoxedHandle(type)
NullableTypeName: Model.OpaqueRecord.GetFullyQuallifiedInternalBoxedHandle(type)
);
}
}
67 changes: 67 additions & 0 deletions src/Generation/Generator/Renderer/Internal/OpaqueRecordHandle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using Generator.Model;

namespace Generator.Renderer.Internal;

internal static class OpaqueRecordHandle
{
public static string Render(GirModel.Record record)
{
var typeName = Model.OpaqueRecord.GetInternalBoxedHandle(record);
var initiallyUnownedBoxedHandleTypeName = Model.OpaqueRecord.GetInternalInitiallyUnownedBoxedHandle(record);
var ownedBoxedHandleTypeName = Model.OpaqueRecord.GetInternalOwnedBoxedHandle(record);
var getGType = Model.OpaqueRecord.GetFullyQualifiedInternalClassName(record) + ".GetGType()";

return $@"using System;
using GObject;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
#nullable enable
namespace {Namespace.GetInternalName(record.Namespace)};
// AUTOGENERATED FILE - DO NOT MODIFY
{PlatformSupportAttribute.Render(record as GirModel.PlatformDependent)}
public partial class {typeName} : SafeHandle
{{
public static readonly {typeName} NullHandle = new (IntPtr.Zero, false);
public sealed override bool IsInvalid => handle == IntPtr.Zero;
public {typeName}(IntPtr handle, bool ownsHandle) : base(IntPtr.Zero, true)
{{
if (!ownsHandle)
handle = GLib.Internal.Functions.BoxedCopy({getGType}, handle);
SetHandle(handle);
}}
public {typeName}(bool ownsHandle) : base(IntPtr.Zero, ownsHandle)
{{
throw new Exception(""How to free??"");
}}
public {typeName} Copy()
{{
return new (handle, false);
}}
protected override bool ReleaseHandle()
{{
GLib.Internal.Functions.BoxedFree({getGType}, handle);
return true;
}}
}}
public class {initiallyUnownedBoxedHandleTypeName} : {typeName}
{{
public {initiallyUnownedBoxedHandleTypeName}() : base(false) {{ }}
}}
public class {ownedBoxedHandleTypeName} : {typeName}
{{
public {ownedBoxedHandleTypeName}() : base(true) {{ }}
}}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ private static string GetNullableTypeName(GirModel.Parameter parameter)
var type = (GirModel.Record) parameter.AnyTypeOrVarArgs.AsT0.AsT0;
return parameter switch
{
{ Direction: GirModel.Direction.In, Transfer: GirModel.Transfer.None } => Model.OpaqueRecord.GetBoxedHandle(type) + Nullable.Render(parameter),
{ Direction: GirModel.Direction.In, Transfer: GirModel.Transfer.Full } => Model.OpaqueRecord.GetBoxedHandle(type) + Nullable.Render(parameter),
{ Direction: GirModel.Direction.In, Transfer: GirModel.Transfer.None } => Model.OpaqueRecord.GetFullyQuallifiedInternalBoxedHandle(type) + Nullable.Render(parameter),
{ Direction: GirModel.Direction.In, Transfer: GirModel.Transfer.Full } => Model.OpaqueRecord.GetFullyQuallifiedInternalBoxedHandle(type) + Nullable.Render(parameter),
{ Direction: GirModel.Direction.Out, Transfer: GirModel.Transfer.Full } => Model.OpaqueRecord.GetFullyQuallifiedInternalBoxedHandle(type) + Nullable.Render(parameter),
{ Direction: GirModel.Direction.Out, Transfer: GirModel.Transfer.None } => Model.OpaqueRecord.GetFullyQuallifiedInternalBoxedHandle(type) + Nullable.Render(parameter),
_ => throw new System.Exception($"Can't detect opaque record parameter type {parameter.Name}: CallerAllocates={parameter.CallerAllocates} Direction={parameter.Direction} Transfer={parameter.Transfer}")
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;

namespace Generator.Renderer.Internal.ParameterToManagedExpressions;

internal class OpaqueRecord : ToManagedParameterConverter
{
public bool Supports(GirModel.AnyType type)
=> type.Is<GirModel.Record>(out var record) && record is { Opaque: true, TypeFunction: not null };

public void Initialize(ParameterToManagedData parameterData, IEnumerable<ParameterToManagedData> parameters)
{
if (parameterData.Parameter.Direction != GirModel.Direction.In)
throw new NotImplementedException($"{parameterData.Parameter.AnyTypeOrVarArgs}: opaque record with direction != in not yet supported");

var record = (GirModel.Record) parameterData.Parameter.AnyTypeOrVarArgs.AsT0.AsT0;
var variableName = Model.Parameter.GetConvertedName(parameterData.Parameter);

var signatureName = Model.Parameter.GetName(parameterData.Parameter);

parameterData.SetSignatureName(signatureName);
parameterData.SetExpression($"var {variableName} = new {Model.OpaqueRecord.GetFullyQualifiedPublicClassName(record)}({signatureName});");
parameterData.SetCallName(variableName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal static class ParameterToManagedExpression
new ParameterToManagedExpressions.Class(),
new ParameterToManagedExpressions.Enumeration(),
new ParameterToManagedExpressions.Interface(),
new ParameterToManagedExpressions.OpaqueRecord(),
new ParameterToManagedExpressions.Pointer(),
new ParameterToManagedExpressions.PointerAlias(),
new ParameterToManagedExpressions.PrimitiveValueType(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public RenderableReturnType Convert(GirModel.ReturnType returnType)

var typeName = returnType switch
{
{Transfer: Transfer.Full} => Model.OpaqueRecord.GetOwnedBoxedHandle(type),
_ => Model.OpaqueRecord.GetInitiallyUnownedBoxedHandle(type)
{Transfer: Transfer.Full} => Model.OpaqueRecord.GetFullyQuallifiedOwnedBoxedHandle(type),
_ => Model.OpaqueRecord.GetFullyQuallifiedInitiallyUnownedBoxedHandle(type)
};

return new RenderableReturnType(typeName + Nullable.Render(returnType));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using GirModel;

namespace Generator.Renderer.Internal.ReturnType;

internal class OpaqueRecordCallback : ReturnTypeConverter
{
public bool Supports(GirModel.ReturnType returnType)
{
return returnType.AnyType.Is<GirModel.Record>(out var record) && record is { Opaque: true, TypeFunction: not null };
}

public RenderableReturnType Convert(GirModel.ReturnType returnType)
{
var type = (GirModel.Record) returnType.AnyType.AsT0;
var typeName = Model.OpaqueRecord.GetFullyQuallifiedInternalBoxedHandle(type);

return new RenderableReturnType(typeName + Nullable.Render(returnType));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ internal static class ReturnTypeRendererCallback
new ReturnType.Enumeration(),
new ReturnType.Interface(),
new ReturnType.InterfaceGLibPtrArray(),
new ReturnType.OpaqueRecordCallback(),
new ReturnType.PlatformStringInCallback(),
new ReturnType.Pointer(),
new ReturnType.PrimitiveValueType(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using GirModel;

namespace Generator.Renderer.Internal.ReturnTypeToNativeExpressions;

internal class OpaqueRecord : ReturnTypeConverter
{
public bool Supports(AnyType type)
=> type.Is<GirModel.Record>(out var record) && record is { Opaque: true, TypeFunction: not null };

public string GetString(GirModel.ReturnType returnType, string fromVariableName)
=> fromVariableName + ".Handle";
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ internal static class ReturnTypeToNativeExpression
new ReturnTypeToNativeExpressions.Class(),
new ReturnTypeToNativeExpressions.Enumeration(),
new ReturnTypeToNativeExpressions.Interface(),
new ReturnTypeToNativeExpressions.OpaqueRecord(),
new ReturnTypeToNativeExpressions.Pointer(),
new ReturnTypeToNativeExpressions.PrimitiveValueType(),
new ReturnTypeToNativeExpressions.PrimitiveValueTypeAlias(),
Expand Down
9 changes: 5 additions & 4 deletions src/Generation/Generator/Renderer/Public/OpaqueRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ internal static class OpaqueRecord
{
public static string Render(GirModel.Record record)
{
var name = Record.GetPublicClassName(record);
var internalHandleName = $"{Namespace.GetInternalName(record.Namespace)}.{Model.Type.GetName(record)}";
var name = Model.OpaqueRecord.GetPublicClassName(record);
var internalHandleName = Model.OpaqueRecord.GetFullyQuallifiedInternalBoxedHandle(record);

return $@"
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
Expand All @@ -25,9 +26,9 @@ namespace {Namespace.GetPublicName(record.Namespace)};
{PlatformSupportAttribute.Render(record as GirModel.PlatformDependent)}
public partial class {name}
{{
public GLib.Internal.BoxedHandle<{internalHandleName}> Handle {{ get; }}
public {internalHandleName} Handle {{ get; }}
public {name}(GLib.Internal.BoxedHandle<{internalHandleName}> handle)
public {name}({internalHandleName} handle)
{{
Handle = handle;
Initialize();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public void Initialize(ParameterToNativeData parameter, IEnumerable<ParameterToN

var callName = parameter.Parameter switch
{
{ Nullable: true, Transfer: GirModel.Transfer.None } => signatureName + "?.Handle ?? " + Model.OpaqueRecord.GetNullBoxedHandle(record),
{ Nullable: true, Transfer: GirModel.Transfer.None } => signatureName + "?.Handle ?? " + Model.OpaqueRecord.GetFullyQuallifiedNullBoxedHandle(record),
{ Nullable: false, Transfer: GirModel.Transfer.None} => signatureName + ".Handle",
{ Nullable: true, Transfer: GirModel.Transfer.Full } => signatureName + "?.Handle.Copy() ?? " + Model.OpaqueRecord.GetNullBoxedHandle(record),
{ Nullable: true, Transfer: GirModel.Transfer.Full } => signatureName + "?.Handle.Copy() ?? " + Model.OpaqueRecord.GetFullyQuallifiedNullBoxedHandle(record),
{ Nullable: false, Transfer: GirModel.Transfer.Full } => signatureName + ".Handle.Copy()",
_ => throw new Exception($"Can't detect call name for parameter opaque parameter {parameter.Parameter.Name}")
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ internal static class ReturnTypeRendererCallback
new ReturnType.Class(),
new ReturnType.Enumeration(),
new ReturnType.Interface(),
new ReturnType.OpaqueRecord(),
new ReturnType.Pointer(),
new ReturnType.PointerAlias(),
new ReturnType.PrimitiveValueType(),
Expand Down
2 changes: 2 additions & 0 deletions src/Libs/GLib-2.0/Internal/BoxedHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@ public class InitiallyUnownedBoxedHandle<T> : BoxedHandle<T> where T : NativeGTy
{
public InitiallyUnownedBoxedHandle(IntPtr handle) : base(handle, false)
{
throw new Exception("TEST IF CALLED");
}
}

public class OwnedBoxedHandle<T> : BoxedHandle<T> where T : NativeGTypeProvider
{
public OwnedBoxedHandle(IntPtr handle) : base(handle, true)
{
throw new Exception("TEST IF CALLED");
}
}
3 changes: 1 addition & 2 deletions src/Libs/GLib-2.0/Public/Variant.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using GLib.Internal;

namespace GLib;

Expand Down Expand Up @@ -42,7 +41,7 @@ public static Variant CreateEmptyDictionary(VariantType key, VariantType value)
return new Variant(Internal.Variant.NewArray(childType, new IntPtr[0], 0));
}

private void Init(out BoxedHandle<GLib.Internal.Variant> handle, params Variant[] children)
private void Init(out GLib.Internal.VariantBoxedHandle handle, params Variant[] children)
{
_children = children;

Expand Down
22 changes: 2 additions & 20 deletions src/Libs/GLib-2.0/Public/VariantType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,12 @@ namespace GLib;

public partial class VariantType : IDisposable
{
#region Static Member

public static readonly VariantType String = new VariantType("s");
public static readonly VariantType Variant = new VariantType("v");

#endregion

#region Constructors

public VariantType(string type) : this(Internal.VariantType.New(Internal.NonNullableUtf8StringOwnedHandle.Create(type))) { }

#endregion

#region Methods
public static readonly VariantType String = New("s");
public static readonly VariantType Variant = New("v");

public override string ToString()
=> Internal.VariantType.PeekString(Handle).ConvertToString();

#endregion

#region IDisposable Implementation

public void Dispose()
=> Handle.Dispose();

#endregion
}
6 changes: 3 additions & 3 deletions src/Libs/Gio-2.0/Public/DBusConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,18 @@ public Task<Variant> CallAsync(string busName, string objectPath, string interfa
Internal.DBusConnection.Call(Handle,
GLib.Internal.NullableUtf8StringOwnedHandle.Create(busName), GLib.Internal.NonNullableUtf8StringOwnedHandle.Create(objectPath),
GLib.Internal.NonNullableUtf8StringOwnedHandle.Create(interfaceName), GLib.Internal.NonNullableUtf8StringOwnedHandle.Create(methodName),
parameters.GetSafeHandle(), GLib.Internal.VariantTypeNullHandle.Instance, DBusCallFlags.None, -1, IntPtr.Zero, callbackHandler.NativeCallback, IntPtr.Zero);
parameters?.Handle, null, DBusCallFlags.None, -1, IntPtr.Zero, callbackHandler.NativeCallback, IntPtr.Zero);

return tcs.Task;
}

public Variant Call(string busName, string objectPath, string interfaceName, string methodName, Variant? parameters = null)
{
var parameterHandle = parameters?.Handle ?? GLib.Internal.VariantNullHandle.Instance;
var parameterHandle = parameters?.Handle;
var ret = Internal.DBusConnection.CallSync(Handle,
GLib.Internal.NullableUtf8StringOwnedHandle.Create(busName), GLib.Internal.NonNullableUtf8StringOwnedHandle.Create(objectPath),
GLib.Internal.NonNullableUtf8StringOwnedHandle.Create(interfaceName), GLib.Internal.NonNullableUtf8StringOwnedHandle.Create(methodName),
parameterHandle, GLib.Internal.VariantTypeNullHandle.Instance, DBusCallFlags.None, 9999, IntPtr.Zero, out var error);
parameterHandle, null, DBusCallFlags.None, 9999, IntPtr.Zero, out var error);

if (!error.IsInvalid)
throw new GException(error);
Expand Down
Loading

0 comments on commit 99f7233

Please sign in to comment.