[perf] Add unmanaged constraint to some APIs to allow pinning, and not manual GCHandle code (#7561)

Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>
Co-authored-by: GitHub Actions Autoformatter <github-actions-autoformatter@xamarin.com>
This commit is contained in:
Marius Ungureanu 2022-11-11 09:58:46 +02:00 коммит произвёл GitHub
Родитель df2fcad671
Коммит 2bd6433fda
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 27 добавлений и 19 удалений

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

@ -643,26 +643,25 @@ namespace AudioToolbox {
return GetArray<AudioValueRange> (prop, sizeof (AudioValueRange));
}
unsafe T []? GetArray<T> (AudioConverterPropertyID prop, int elementSize)
unsafe T []? GetArray<T> (AudioConverterPropertyID prop, int elementSize) where T : unmanaged
{
int size;
bool writable;
if (AudioConverterGetPropertyInfo (Handle, prop, out size, out writable) != AudioConverterError.None)
return null;
var data = new T [size / elementSize];
var array_handle = GCHandle.Alloc (data, GCHandleType.Pinned); // This requires a pinned GCHandle, since it's not possible to use unsafe code to get the address of a generic object.
if (size == 0)
return Array.Empty<T> ();
try {
var ptr = array_handle.AddrOfPinnedObject ();
var res = AudioConverterGetProperty (Handle, prop, ref size, ptr);
var data = new T [size / elementSize];
fixed (T* ptr = data) {
var res = AudioConverterGetProperty (Handle, prop, ref size, (IntPtr) ptr);
if (res != 0)
return null;
Array.Resize (ref data, size / elementSize);
return data;
} finally {
array_handle.Free ();
}
}

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

@ -65,26 +65,25 @@ namespace AudioToolbox {
return GetAvailable<AudioClassDescription> (AudioFormatProperty.Encoders, format);
}
unsafe static T []? GetAvailable<T> (AudioFormatProperty prop, AudioFormatType format)
unsafe static T []? GetAvailable<T> (AudioFormatProperty prop, AudioFormatType format) where T : unmanaged
{
uint size;
if (AudioFormatPropertyNative.AudioFormatGetPropertyInfo (prop, sizeof (AudioFormatType), ref format, out size) != 0)
return null;
var data = new T [size / Marshal.SizeOf (typeof (T))];
var array_handle = GCHandle.Alloc (data, GCHandleType.Pinned); // This requires a pinned GCHandle, since it's not possible to use unsafe code to get the address of a generic object.
if (size == 0)
return Array.Empty<T> ();
try {
var ptr = array_handle.AddrOfPinnedObject ();
var res = AudioFormatPropertyNative.AudioFormatGetProperty (prop, sizeof (AudioFormatType), ref format, ref size, ptr);
var data = new T [size / Marshal.SizeOf (typeof (T))];
fixed (T* ptr = data) {
var res = AudioFormatPropertyNative.AudioFormatGetProperty (prop, sizeof (AudioFormatType), ref format, ref size, (IntPtr) ptr);
if (res != 0)
return null;
Array.Resize (ref data, (int) size / Marshal.SizeOf (typeof (T)));
return data;
} finally {
array_handle.Free ();
}
Array.Resize (ref data, (int) size / sizeof (T));
return data;
}
}

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

@ -4,6 +4,8 @@
#if !__WATCHOS__
using System.Runtime.InteropServices;
using NUnit.Framework;
using Foundation;
@ -80,6 +82,14 @@ namespace MonoTouchFixtures.AudioUnit {
var icon = component.CopyIcon (); // ensuring that the manual binding does not throw, we do not care about the result
});
}
[Test]
public unsafe void TestSizeOf()
{
Assert.AreEqual (sizeof (AudioFormat), Marshal.SizeOf (typeof (AudioFormat)));
Assert.AreEqual (sizeof (AudioValueRange), Marshal.SizeOf (typeof (AudioValueRange)));
Assert.AreEqual (sizeof (AudioClassDescription), Marshal.SizeOf (typeof (AudioClassDescription)));
}
}
}