[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:
Родитель
df2fcad671
Коммит
2bd6433fda
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче