Skip to content

Commit

Permalink
Merge pull request #775 from gircore/signal-return-value
Browse files Browse the repository at this point in the history
  • Loading branch information
badcel authored Feb 5, 2023
2 parents 6b7b77f + ed1b239 commit d95c297
Show file tree
Hide file tree
Showing 24 changed files with 406 additions and 130 deletions.
32 changes: 31 additions & 1 deletion src/Generation/Generator/Model/Signal.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Generator.Model;
using System.Linq;

namespace Generator.Model;

internal static class Signal
{
Expand All @@ -16,4 +18,32 @@ public static string GetArgsClassName(GirModel.Signal signal)
{
return signal.Name.ToPascalCase() + "SignalArgs";
}

public static string GetDescriptorClassName(GirModel.Signal signal, GirModel.Class cls)
{
return signal.ReturnType.AnyType.Is<GirModel.Void>()
? $"Signal<{GetGenericArgs(signal, cls)}>"
: $"ReturningSignal<{GetGenericReturningArgs(signal, cls)}>";
}

public static string GetDelegateName(GirModel.Signal signal, GirModel.Class cls)
{
return signal.ReturnType.AnyType.Is<GirModel.Void>()
? $"SignalHandler<{GetGenericArgs(signal, cls)}>"
: $"ReturningSignalHandler<{GetGenericReturningArgs(signal, cls)}>";
}

private static string GetGenericArgs(GirModel.Signal signal, GirModel.Class cls)
{
return signal.Parameters.Any()
? $"{cls.Name}, {GetArgsClassName(signal)}"
: cls.Name;
}

private static string GetGenericReturningArgs(GirModel.Signal signal, GirModel.Class cls)
{
return signal.Parameters.Any()
? $"{cls.Name}, {GetArgsClassName(signal)}, {Renderer.Public.ReturnType.Render(signal.ReturnType)}"
: $"{cls.Name}, {Renderer.Public.ReturnType.Render(signal.ReturnType)}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ private static string RenderDescriptor(GirModel.Class cls, GirModel.Signal signa
/// <summary>
/// Signal Descriptor for {Signal.GetName(signal)}.
/// </summary>
public static readonly Signal<{GetGenericArgs(cls, signal)}> {Signal.GetDescriptorName(signal)} = new (
public static readonly {Signal.GetDescriptorClassName(signal, cls)} {Signal.GetDescriptorName(signal)} = new (
unmanagedName: ""{signal.Name}"",
managedName: nameof({Signal.GetName(signal)})
);";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public static partial class ClassSignal
private static string RenderEvent(GirModel.Class cls, GirModel.Signal signal)
{
return $@"
public event SignalHandler<{GetGenericArgs(cls, signal)}> {Signal.GetName(signal)}
public event {Signal.GetDelegateName(signal, cls)} {Signal.GetName(signal)}
{{
add => {Signal.GetDescriptorName(signal)}.Connect(this, value);
remove => {Signal.GetDescriptorName(signal)}.Disconnect(this, value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,4 @@ public static string Render(GirModel.Class cls, GirModel.Signal signal)
return string.Empty;
}
}

private static string GetGenericArgs(GirModel.Class cls, GirModel.Signal signal)
{
return signal.Parameters.Any()
? $"{cls.Name}, {Signal.GetArgsClassName(signal)}"
: cls.Name;
}
}
1 change: 1 addition & 0 deletions src/Generation/GirLoader/Output/Signal.GirModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ public partial class Signal : GirModel.Signal
{
string GirModel.Signal.Name => Name;
IEnumerable<GirModel.Parameter> GirModel.Signal.Parameters => ParameterList.SingleParameters;
GirModel.ReturnType GirModel.Signal.ReturnType => ReturnValue;
bool GirModel.Signal.Introspectable => Introspectable;
}
1 change: 1 addition & 0 deletions src/Generation/GirModel/Signal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ public interface Signal
{
string Name { get; }
IEnumerable<Parameter> Parameters { get; }
ReturnType ReturnType { get; }
bool Introspectable { get; }
}
20 changes: 20 additions & 0 deletions src/Libs/GObject-2.0/Public/ReturningSignalHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace GObject;

/// <summary>
/// SignalHandler for signals without any extra data.
/// </summary>
/// <param name="sender">The sender of this signal.</param>
/// <param name="args">Event args. Will always have the value of <see cref="EventArgs.Empty"/>.</param>
public delegate TReturn ReturningSignalHandler<in TSender, out TReturn>(TSender sender, EventArgs args)
where TSender : Object;

/// <summary>
/// SignalHandler for signals with extra data.
/// </summary>
/// <param name="sender">The sender of this signal.</param>
/// <param name="args"><see cref="SignalArgs"/> with additional data.</param>
public delegate TReturn ReturningSignalHandler<in TSender, in TSignalArgs, out TReturn>(TSender sender, TSignalArgs args)
where TSender : Object
where TSignalArgs : SignalArgs;
62 changes: 62 additions & 0 deletions src/Libs/GObject-2.0/Public/ReturningSignalTSender.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
namespace GObject;

/// <summary>
/// Describes a GSignal.
/// </summary>
public class ReturningSignal<TSender, TReturn> : SignalDefinition
where TSender : Object, GTypeProvider
{
private uint? _id;

public string UnmanagedName { get; }
public string ManagedName { get; }
public uint Id => _id ??= GetId();

public ReturningSignal(string unmanagedName, string managedName)
{
UnmanagedName = unmanagedName;
ManagedName = managedName;
}

private uint GetId()
{
#if NET7_0_OR_GREATER
var gType = TSender.GetGType();
#else
var gType = Internal.GTypeProviderHelper.GetGType<TSender>();
#endif

return Internal.Functions.SignalLookup(UnmanagedName, gType);
}

/// <summary>
/// Connects a <paramref name="signalHandler"/> to this signal.
/// </summary>
/// <param name="o">The object on which connect the handler.</param>
/// <param name="signalHandler">The signal handler function.</param>
/// <param name="after">Define if this action must be called before or after the default handler of this signal.</param>
/// <param name="detail">Define for which signal detail the connection should be made.</param>
public void Connect(TSender o, ReturningSignalHandler<TSender, TReturn> signalHandler, bool after = false, string? detail = null)
{
var closure = new Closure((returnValue, parameters) =>
{
if (returnValue is null)
throw new System.Exception($"{nameof(TSender)}.{ManagedName}: C did not provide a value pointer to return the signal result");

var result = signalHandler(o, System.EventArgs.Empty);
returnValue.Set(result);
});

o.SignalConnectClosure(this, signalHandler, closure, after, detail);
}

/// <summary>
/// Disconnects a <paramref name="signalHandler"/> previously connected to this signal.
/// </summary>
/// <param name="o">The object from which disconnect the handler.</param>
/// <param name="signalHandler">The signal handler function.</param>
public void Disconnect(TSender o, ReturningSignalHandler<TSender, TReturn> signalHandler)
{
o.Disconnect(this, signalHandler);
}
}
66 changes: 66 additions & 0 deletions src/Libs/GObject-2.0/Public/ReturningSignalTSenderTSignalArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
namespace GObject;

/// <summary>
/// Describes a GSignal.
/// </summary>
public class ReturningSignal<TSender, TSignalArgs, TReturn> : SignalDefinition
where TSender : Object, GTypeProvider
where TSignalArgs : SignalArgs, new()
{
private uint? _id;

public string UnmanagedName { get; }
public string ManagedName { get; }
public uint Id => _id ??= GetId();

public ReturningSignal(string unmanagedName, string managedName)
{
UnmanagedName = unmanagedName;
ManagedName = managedName;
}

private uint GetId()
{
#if NET7_0_OR_GREATER
var gType = TSender.GetGType();
#else
var gType = Internal.GTypeProviderHelper.GetGType<TSender>();
#endif

return Internal.Functions.SignalLookup(UnmanagedName, gType);
}

/// <summary>
/// Connects a <paramref name="signalHandler"/> to this signal.
/// </summary>
/// <param name="o">The object on which connect the handler.</param>
/// <param name="signalHandler">The signal handler function.</param>
/// <param name="after">Define if this action must be called before or after the default handler of this signal.</param>
/// <param name="detail">Define for which signal detail the connection should be made.</param>
public void Connect(TSender o, ReturningSignalHandler<TSender, TSignalArgs, TReturn> signalHandler, bool after = false, string? detail = null)
{
var closure = new Closure((returnValue, parameters) =>
{
if (returnValue is null)
throw new System.Exception($"{nameof(TSender)}.{ManagedName}: C did not provide a value pointer to return the signal result");

var args = new TSignalArgs();
args.SetArgs(parameters);

var result = signalHandler(o, args);
returnValue.Set(result);
});

o.SignalConnectClosure(this, signalHandler, closure, after, detail);
}

/// <summary>
/// Disconnects a <paramref name="signalHandler"/> previously connected to this signal.
/// </summary>
/// <param name="o">The object from which disconnect the handler.</param>
/// <param name="signalHandler">The signal handler function.</param>
public void Disconnect(TSender o, ReturningSignalHandler<TSender, TSignalArgs, TReturn> signalHandler)
{
o.Disconnect(this, signalHandler);
}
}
36 changes: 0 additions & 36 deletions src/Native/GirTestLib/classtype.c

This file was deleted.

16 changes: 0 additions & 16 deletions src/Native/GirTestLib/classtype.h

This file was deleted.

36 changes: 36 additions & 0 deletions src/Native/GirTestLib/girtest-class-tester.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "girtest-class-tester.h"

/**
* GirTestClassTester:
*
* Contains functions for testing bindings with class types.
*/

struct _GirTestClassTester
{
GObject parent_instance;
};

G_DEFINE_TYPE(GirTestClassTester, girtest_class_tester, G_TYPE_OBJECT)

static void
girtest_class_tester_init(GirTestClassTester *value)
{
}

static void
girtest_class_tester_class_init(GirTestClassTesterClass *class)
{
}

/**
* girtest_class_tester_transfer_ownership_full_and_unref:
* @object: (transfer full): Any object
*
* Simple test to transfer ownership to C. The object is unrefed immediately.
*/
void
girtest_class_tester_transfer_ownership_full_and_unref(GObject *object)
{
g_object_unref(object);
}
15 changes: 15 additions & 0 deletions src/Native/GirTestLib/girtest-class-tester.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include <glib-object.h>

G_BEGIN_DECLS

#define GIRTEST_TYPE_CLASS_TESTER girtest_class_tester_get_type()

G_DECLARE_FINAL_TYPE(GirTestClassTester, girtest_class_tester, GIRTEST, CLASS_TESTER, GObject)

void
girtest_class_tester_transfer_ownership_full_and_unref(GObject *object);

G_END_DECLS

38 changes: 38 additions & 0 deletions src/Native/GirTestLib/girtest-primitive-value-type-tester.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "girtest-primitive-value-type-tester.h"

/**
* GirTestPrimitiveValueTypeTester:
*
* Contains functions for testing bindings with primitive value types.
*/

struct _GirTestPrimitiveValueTypeTester
{
GObject parent_instance;
};

G_DEFINE_TYPE(GirTestPrimitiveValueTypeTester, girtest_primitive_value_type_tester, G_TYPE_OBJECT)

static void
girtest_primitive_value_type_tester_init(GirTestPrimitiveValueTypeTester *value)
{
}

static void
girtest_primitive_value_type_tester_class_init(GirTestPrimitiveValueTypeTesterClass *class)
{
}

/**
* girtest_primitive_value_type_tester_int_in:
* @val: (in): An integer value
*
* Simple test for an input integer parameter.
*
* Returns: The input value multiplied by 2
*/
int
girtest_primitive_value_type_tester_int_in(int val)
{
return 2 * val;
}
16 changes: 16 additions & 0 deletions src/Native/GirTestLib/girtest-primitive-value-type-tester.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <glib-object.h>

G_BEGIN_DECLS

#define GIRTEST_TYPE_PRIMITIVE_VALUE_TYPE_TESTER girtest_primitive_value_type_tester_get_type()

G_DECLARE_FINAL_TYPE(GirTestPrimitiveValueTypeTester, girtest_primitive_value_type_tester,
GIRTEST, PRIMITIVE_VALUE_TYPE_TESTER, GObject)

int
girtest_primitive_value_type_tester_int_in(int val);

G_END_DECLS

Loading

0 comments on commit d95c297

Please sign in to comment.