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 8789d26
Show file tree
Hide file tree
Showing 26 changed files with 262 additions and 52 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.GetInternalHandle(obj),
Source: source,
IsInternal: true
);

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

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 GetInternalHandle(GirModel.Record record)
=> $"{Type.GetName(record)}Handle";

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

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

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

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

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

public static string GetFullyQuallifiedInitiallyUnownedBoxedHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetInternalInitiallyUnownedHandle(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)}NullHandle.Instance";
}
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.GetFullyQuallifiedInternalHandle(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.GetInternalHandle(record);
var initiallyUnownedHandleTypeName = Model.OpaqueRecord.GetInternalInitiallyUnownedHandle(record);
var ownedHandleTypeName = Model.OpaqueRecord.GetInternalOwnedHandle(record);
var nullHandleTypeName = Model.OpaqueRecord.GetInternalNullHandle(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 sealed override bool IsInvalid => handle == IntPtr.Zero;
protected {typeName}(bool ownsHandle) : base(IntPtr.Zero, ownsHandle) {{ }}
protected override bool ReleaseHandle()
{{
GLib.Internal.Functions.BoxedFree({getGType}, handle);
return true;
}}
public {typeName} Copy()
{{
var ptr = GLib.Internal.Functions.BoxedCopy({getGType}, handle);
var obj = new {typeName}(true);
obj.SetHandle(ptr);
return obj;
}}
}}
public class {initiallyUnownedHandleTypeName} : {typeName}
{{
//Constructor for PInvoke
private {initiallyUnownedHandleTypeName}() : base(false) {{ }}
}}
public class {ownedHandleTypeName} : {typeName}
{{
//Constructor for PInvoke
private {ownedHandleTypeName}() : base(true) {{ }}
}}
public class {nullHandleTypeName} : {typeName}
{{
public static {nullHandleTypeName} Instance = new ();
private {nullHandleTypeName}() : base(false) {{ }}
}}";
}
}
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.GetFullyQuallifiedInternalHandle(type) + Nullable.Render(parameter),
{ Direction: GirModel.Direction.In, Transfer: GirModel.Transfer.Full } => Model.OpaqueRecord.GetFullyQuallifiedInternalHandle(type) + Nullable.Render(parameter),
{ Direction: GirModel.Direction.Out, Transfer: GirModel.Transfer.Full } => Model.OpaqueRecord.GetFullyQuallifiedInternalHandle(type) + Nullable.Render(parameter),
{ Direction: GirModel.Direction.Out, Transfer: GirModel.Transfer.None } => Model.OpaqueRecord.GetFullyQuallifiedInternalHandle(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.GetFullyQuallifiedOwnedHandle(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.GetFullyQuallifiedInternalHandle(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.GetFullyQuallifiedInternalHandle(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");
}
}
4 changes: 2 additions & 2 deletions src/Libs/GLib-2.0/Internal/Functions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ namespace GLib.Internal;

public partial class Functions
{
[DllImport(ImportResolver.Library, EntryPoint = "g_boxed_copy")]
[DllImport(GObject.Internal.ImportResolver.Library, EntryPoint = "g_boxed_copy")]
public static extern IntPtr BoxedCopy(nuint boxedType, IntPtr srcBoxed);

[DllImport(ImportResolver.Library, EntryPoint = "g_boxed_free")]
[DllImport(GObject.Internal.ImportResolver.Library, EntryPoint = "g_boxed_free")]
public static extern void BoxedFree(nuint boxedType, IntPtr boxed);
}
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.VariantHandle 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
}
Loading

0 comments on commit 8789d26

Please sign in to comment.