[bgen] Add support for delegates with pointer types. (#21159)

This commit is contained in:
Rolf Bjarne Kvinge 2024-09-02 15:02:39 +02:00 коммит произвёл GitHub
Родитель ff707c145e
Коммит 3b6a5c20c6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
3 изменённых файлов: 42 добавлений и 2 удалений

Просмотреть файл

@ -718,6 +718,14 @@ public partial class Generator : IMemberGatherer {
}
}
if (pi.ParameterType.IsPointer && pi.ParameterType.GetElementType ().IsValueType) {
// Technically we should only allow blittable types here, but the C# compiler shows an error later on if any non-blittable types
// are used, because this ends up in the signature of a UnmanagedCallersOnly method.
pars.Add (new TrampolineParameterInfo (TypeManager.FormatType (null, pi.ParameterType), safe_name));
invoke.Append (safe_name);
continue;
}
if (pi.ParameterType.IsSubclassOf (TypeCache.System_Delegate)) {
if (!delegate_types.ContainsKey (pi.ParameterType.Name)) {
delegate_types [pi.ParameterType.FullName] = pi.ParameterType.GetMethod ("Invoke");
@ -4731,11 +4739,13 @@ public partial class Generator : IMemberGatherer {
print ("[MonoNativeFunctionWrapper]\n");
var accessibility = mi.DeclaringType.IsInternal (this) ? "internal" : "public";
print ("{3} delegate {0} {1} ({2});",
var isUnsafe = mi.GetParameters ().Any ((v => v.ParameterType.IsPointer)) || mi.ReturnType.IsPointer;
print ("{3}{4} delegate {0} {1} ({2});",
TypeManager.RenderType (mi.ReturnType, mi.ReturnTypeCustomAttributes),
shortName,
RenderParameterDecl (mi.GetParameters ()),
accessibility);
accessibility,
isUnsafe ? " unsafe" : string.Empty);
}
if (group.Namespace is not null) {

Просмотреть файл

@ -1719,5 +1719,20 @@ namespace GeneratorTests {
var delegateCallback = bgen.ApiAssembly.MainModule.GetType ("NS", "MyCallback").Methods.First ((v) => v.Name == "EndInvoke");
Assert.That (delegateCallback.MethodReturnType.CustomAttributes.Any (v => v.AttributeType.Name == "NullableAttribute"), "Nullable return type");
}
[Test]
[TestCase (Profile.iOS)]
public void DelegatesWithPointerTypes (Profile profile)
{
Configuration.IgnoreIfIgnoredPlatform (profile.AsPlatform ());
var bgen = BuildFile (profile, "tests/delegate-types.cs");
bgen.AssertNoWarnings ();
var delegateCallback = bgen.ApiAssembly.MainModule.GetType ("NS", "MyCallback").Methods.First ((v) => v.Name == "EndInvoke");
Assert.IsTrue (delegateCallback.MethodReturnType.ReturnType.IsPointer, "Pointer return type");
foreach (var p in delegateCallback.Parameters.Where (v => v.Name != "result")) {
Assert.IsTrue (p.ParameterType.IsPointer, $"Pointer parameter type: {p.Name}");
}
}
}
}

Просмотреть файл

@ -0,0 +1,15 @@
using System;
using Foundation;
using ObjCRuntime;
namespace NS {
unsafe delegate byte* MyCallback (sbyte* a, short* b, ushort* c, int* d, uint* e, long* f, ulong* g, float* h, double* i);
[BaseType (typeof (NSObject))]
interface Widget {
[Export ("foo")]
[NullAllowed]
MyCallback Foo { get; set; }
}
}