Skip to content

Commit d95c297

Browse files
authored
Merge pull request #775 from gircore/signal-return-value
2 parents 6b7b77f + ed1b239 commit d95c297

24 files changed

+406
-130
lines changed

src/Generation/Generator/Model/Signal.cs

+31-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace Generator.Model;
1+
using System.Linq;
2+
3+
namespace Generator.Model;
24

35
internal static class Signal
46
{
@@ -16,4 +18,32 @@ public static string GetArgsClassName(GirModel.Signal signal)
1618
{
1719
return signal.Name.ToPascalCase() + "SignalArgs";
1820
}
21+
22+
public static string GetDescriptorClassName(GirModel.Signal signal, GirModel.Class cls)
23+
{
24+
return signal.ReturnType.AnyType.Is<GirModel.Void>()
25+
? $"Signal<{GetGenericArgs(signal, cls)}>"
26+
: $"ReturningSignal<{GetGenericReturningArgs(signal, cls)}>";
27+
}
28+
29+
public static string GetDelegateName(GirModel.Signal signal, GirModel.Class cls)
30+
{
31+
return signal.ReturnType.AnyType.Is<GirModel.Void>()
32+
? $"SignalHandler<{GetGenericArgs(signal, cls)}>"
33+
: $"ReturningSignalHandler<{GetGenericReturningArgs(signal, cls)}>";
34+
}
35+
36+
private static string GetGenericArgs(GirModel.Signal signal, GirModel.Class cls)
37+
{
38+
return signal.Parameters.Any()
39+
? $"{cls.Name}, {GetArgsClassName(signal)}"
40+
: cls.Name;
41+
}
42+
43+
private static string GetGenericReturningArgs(GirModel.Signal signal, GirModel.Class cls)
44+
{
45+
return signal.Parameters.Any()
46+
? $"{cls.Name}, {GetArgsClassName(signal)}, {Renderer.Public.ReturnType.Render(signal.ReturnType)}"
47+
: $"{cls.Name}, {Renderer.Public.ReturnType.Render(signal.ReturnType)}";
48+
}
1949
}

src/Generation/Generator/Renderer/Public/Class/Signals/ClassSignal.Descriptor.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ private static string RenderDescriptor(GirModel.Class cls, GirModel.Signal signa
1010
/// <summary>
1111
/// Signal Descriptor for {Signal.GetName(signal)}.
1212
/// </summary>
13-
public static readonly Signal<{GetGenericArgs(cls, signal)}> {Signal.GetDescriptorName(signal)} = new (
13+
public static readonly {Signal.GetDescriptorClassName(signal, cls)} {Signal.GetDescriptorName(signal)} = new (
1414
unmanagedName: ""{signal.Name}"",
1515
managedName: nameof({Signal.GetName(signal)})
1616
);";

src/Generation/Generator/Renderer/Public/Class/Signals/ClassSignal.Event.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public static partial class ClassSignal
77
private static string RenderEvent(GirModel.Class cls, GirModel.Signal signal)
88
{
99
return $@"
10-
public event SignalHandler<{GetGenericArgs(cls, signal)}> {Signal.GetName(signal)}
10+
public event {Signal.GetDelegateName(signal, cls)} {Signal.GetName(signal)}
1111
{{
1212
add => {Signal.GetDescriptorName(signal)}.Connect(this, value);
1313
remove => {Signal.GetDescriptorName(signal)}.Disconnect(this, value);

src/Generation/Generator/Renderer/Public/Class/Signals/ClassSignal.cs

-7
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,4 @@ public static string Render(GirModel.Class cls, GirModel.Signal signal)
3030
return string.Empty;
3131
}
3232
}
33-
34-
private static string GetGenericArgs(GirModel.Class cls, GirModel.Signal signal)
35-
{
36-
return signal.Parameters.Any()
37-
? $"{cls.Name}, {Signal.GetArgsClassName(signal)}"
38-
: cls.Name;
39-
}
4033
}

src/Generation/GirLoader/Output/Signal.GirModel.cs

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ public partial class Signal : GirModel.Signal
66
{
77
string GirModel.Signal.Name => Name;
88
IEnumerable<GirModel.Parameter> GirModel.Signal.Parameters => ParameterList.SingleParameters;
9+
GirModel.ReturnType GirModel.Signal.ReturnType => ReturnValue;
910
bool GirModel.Signal.Introspectable => Introspectable;
1011
}

src/Generation/GirModel/Signal.cs

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ public interface Signal
66
{
77
string Name { get; }
88
IEnumerable<Parameter> Parameters { get; }
9+
ReturnType ReturnType { get; }
910
bool Introspectable { get; }
1011
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
3+
namespace GObject;
4+
5+
/// <summary>
6+
/// SignalHandler for signals without any extra data.
7+
/// </summary>
8+
/// <param name="sender">The sender of this signal.</param>
9+
/// <param name="args">Event args. Will always have the value of <see cref="EventArgs.Empty"/>.</param>
10+
public delegate TReturn ReturningSignalHandler<in TSender, out TReturn>(TSender sender, EventArgs args)
11+
where TSender : Object;
12+
13+
/// <summary>
14+
/// SignalHandler for signals with extra data.
15+
/// </summary>
16+
/// <param name="sender">The sender of this signal.</param>
17+
/// <param name="args"><see cref="SignalArgs"/> with additional data.</param>
18+
public delegate TReturn ReturningSignalHandler<in TSender, in TSignalArgs, out TReturn>(TSender sender, TSignalArgs args)
19+
where TSender : Object
20+
where TSignalArgs : SignalArgs;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
namespace GObject;
2+
3+
/// <summary>
4+
/// Describes a GSignal.
5+
/// </summary>
6+
public class ReturningSignal<TSender, TReturn> : SignalDefinition
7+
where TSender : Object, GTypeProvider
8+
{
9+
private uint? _id;
10+
11+
public string UnmanagedName { get; }
12+
public string ManagedName { get; }
13+
public uint Id => _id ??= GetId();
14+
15+
public ReturningSignal(string unmanagedName, string managedName)
16+
{
17+
UnmanagedName = unmanagedName;
18+
ManagedName = managedName;
19+
}
20+
21+
private uint GetId()
22+
{
23+
#if NET7_0_OR_GREATER
24+
var gType = TSender.GetGType();
25+
#else
26+
var gType = Internal.GTypeProviderHelper.GetGType<TSender>();
27+
#endif
28+
29+
return Internal.Functions.SignalLookup(UnmanagedName, gType);
30+
}
31+
32+
/// <summary>
33+
/// Connects a <paramref name="signalHandler"/> to this signal.
34+
/// </summary>
35+
/// <param name="o">The object on which connect the handler.</param>
36+
/// <param name="signalHandler">The signal handler function.</param>
37+
/// <param name="after">Define if this action must be called before or after the default handler of this signal.</param>
38+
/// <param name="detail">Define for which signal detail the connection should be made.</param>
39+
public void Connect(TSender o, ReturningSignalHandler<TSender, TReturn> signalHandler, bool after = false, string? detail = null)
40+
{
41+
var closure = new Closure((returnValue, parameters) =>
42+
{
43+
if (returnValue is null)
44+
throw new System.Exception($"{nameof(TSender)}.{ManagedName}: C did not provide a value pointer to return the signal result");
45+
46+
var result = signalHandler(o, System.EventArgs.Empty);
47+
returnValue.Set(result);
48+
});
49+
50+
o.SignalConnectClosure(this, signalHandler, closure, after, detail);
51+
}
52+
53+
/// <summary>
54+
/// Disconnects a <paramref name="signalHandler"/> previously connected to this signal.
55+
/// </summary>
56+
/// <param name="o">The object from which disconnect the handler.</param>
57+
/// <param name="signalHandler">The signal handler function.</param>
58+
public void Disconnect(TSender o, ReturningSignalHandler<TSender, TReturn> signalHandler)
59+
{
60+
o.Disconnect(this, signalHandler);
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
namespace GObject;
2+
3+
/// <summary>
4+
/// Describes a GSignal.
5+
/// </summary>
6+
public class ReturningSignal<TSender, TSignalArgs, TReturn> : SignalDefinition
7+
where TSender : Object, GTypeProvider
8+
where TSignalArgs : SignalArgs, new()
9+
{
10+
private uint? _id;
11+
12+
public string UnmanagedName { get; }
13+
public string ManagedName { get; }
14+
public uint Id => _id ??= GetId();
15+
16+
public ReturningSignal(string unmanagedName, string managedName)
17+
{
18+
UnmanagedName = unmanagedName;
19+
ManagedName = managedName;
20+
}
21+
22+
private uint GetId()
23+
{
24+
#if NET7_0_OR_GREATER
25+
var gType = TSender.GetGType();
26+
#else
27+
var gType = Internal.GTypeProviderHelper.GetGType<TSender>();
28+
#endif
29+
30+
return Internal.Functions.SignalLookup(UnmanagedName, gType);
31+
}
32+
33+
/// <summary>
34+
/// Connects a <paramref name="signalHandler"/> to this signal.
35+
/// </summary>
36+
/// <param name="o">The object on which connect the handler.</param>
37+
/// <param name="signalHandler">The signal handler function.</param>
38+
/// <param name="after">Define if this action must be called before or after the default handler of this signal.</param>
39+
/// <param name="detail">Define for which signal detail the connection should be made.</param>
40+
public void Connect(TSender o, ReturningSignalHandler<TSender, TSignalArgs, TReturn> signalHandler, bool after = false, string? detail = null)
41+
{
42+
var closure = new Closure((returnValue, parameters) =>
43+
{
44+
if (returnValue is null)
45+
throw new System.Exception($"{nameof(TSender)}.{ManagedName}: C did not provide a value pointer to return the signal result");
46+
47+
var args = new TSignalArgs();
48+
args.SetArgs(parameters);
49+
50+
var result = signalHandler(o, args);
51+
returnValue.Set(result);
52+
});
53+
54+
o.SignalConnectClosure(this, signalHandler, closure, after, detail);
55+
}
56+
57+
/// <summary>
58+
/// Disconnects a <paramref name="signalHandler"/> previously connected to this signal.
59+
/// </summary>
60+
/// <param name="o">The object from which disconnect the handler.</param>
61+
/// <param name="signalHandler">The signal handler function.</param>
62+
public void Disconnect(TSender o, ReturningSignalHandler<TSender, TSignalArgs, TReturn> signalHandler)
63+
{
64+
o.Disconnect(this, signalHandler);
65+
}
66+
}

src/Native/GirTestLib/classtype.c

-36
This file was deleted.

src/Native/GirTestLib/classtype.h

-16
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include "girtest-class-tester.h"
2+
3+
/**
4+
* GirTestClassTester:
5+
*
6+
* Contains functions for testing bindings with class types.
7+
*/
8+
9+
struct _GirTestClassTester
10+
{
11+
GObject parent_instance;
12+
};
13+
14+
G_DEFINE_TYPE(GirTestClassTester, girtest_class_tester, G_TYPE_OBJECT)
15+
16+
static void
17+
girtest_class_tester_init(GirTestClassTester *value)
18+
{
19+
}
20+
21+
static void
22+
girtest_class_tester_class_init(GirTestClassTesterClass *class)
23+
{
24+
}
25+
26+
/**
27+
* girtest_class_tester_transfer_ownership_full_and_unref:
28+
* @object: (transfer full): Any object
29+
*
30+
* Simple test to transfer ownership to C. The object is unrefed immediately.
31+
*/
32+
void
33+
girtest_class_tester_transfer_ownership_full_and_unref(GObject *object)
34+
{
35+
g_object_unref(object);
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#pragma once
2+
3+
#include <glib-object.h>
4+
5+
G_BEGIN_DECLS
6+
7+
#define GIRTEST_TYPE_CLASS_TESTER girtest_class_tester_get_type()
8+
9+
G_DECLARE_FINAL_TYPE(GirTestClassTester, girtest_class_tester, GIRTEST, CLASS_TESTER, GObject)
10+
11+
void
12+
girtest_class_tester_transfer_ownership_full_and_unref(GObject *object);
13+
14+
G_END_DECLS
15+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include "girtest-primitive-value-type-tester.h"
2+
3+
/**
4+
* GirTestPrimitiveValueTypeTester:
5+
*
6+
* Contains functions for testing bindings with primitive value types.
7+
*/
8+
9+
struct _GirTestPrimitiveValueTypeTester
10+
{
11+
GObject parent_instance;
12+
};
13+
14+
G_DEFINE_TYPE(GirTestPrimitiveValueTypeTester, girtest_primitive_value_type_tester, G_TYPE_OBJECT)
15+
16+
static void
17+
girtest_primitive_value_type_tester_init(GirTestPrimitiveValueTypeTester *value)
18+
{
19+
}
20+
21+
static void
22+
girtest_primitive_value_type_tester_class_init(GirTestPrimitiveValueTypeTesterClass *class)
23+
{
24+
}
25+
26+
/**
27+
* girtest_primitive_value_type_tester_int_in:
28+
* @val: (in): An integer value
29+
*
30+
* Simple test for an input integer parameter.
31+
*
32+
* Returns: The input value multiplied by 2
33+
*/
34+
int
35+
girtest_primitive_value_type_tester_int_in(int val)
36+
{
37+
return 2 * val;
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#pragma once
2+
3+
#include <glib-object.h>
4+
5+
G_BEGIN_DECLS
6+
7+
#define GIRTEST_TYPE_PRIMITIVE_VALUE_TYPE_TESTER girtest_primitive_value_type_tester_get_type()
8+
9+
G_DECLARE_FINAL_TYPE(GirTestPrimitiveValueTypeTester, girtest_primitive_value_type_tester,
10+
GIRTEST, PRIMITIVE_VALUE_TYPE_TESTER, GObject)
11+
12+
int
13+
girtest_primitive_value_type_tester_int_in(int val);
14+
15+
G_END_DECLS
16+

0 commit comments

Comments
 (0)