Skip to content

Instantly share code, notes, and snippets.

@rolfbjarne
Created April 4, 2016 12:48
Show Gist options
  • Save rolfbjarne/25032e8bb41c9d62a14e68fdbee54a15 to your computer and use it in GitHub Desktop.
Save rolfbjarne/25032e8bb41c9d62a14e68fdbee54a15 to your computer and use it in GitHub Desktop.
commit cbcd66ac57af0a7707b5d66001e523ca26bb4eee
Author: Rolf Bjarne Kvinge <[email protected]>
Date: Mon Apr 4 14:47:20 2016 +0200
[CoreMidi] Avoid the use of fixed buffers.
The C# compiler generates a non-stable backing type for the
fixed buffer, which means we don't control the public API 100%.
It's may even change between executions of the same C# compiler,
which means it breaks our api-diff already.
Example diff:
/Applications/Xcode73.app/Contents/Developer/usr/bin/make verify-reference-assemblies-ios -j8
GEN temp/native-64/Xamarin.iOS.xml
GEN temp/native-32/Xamarin.iOS.xml
--- temp/native-32/Xamarin.iOS.xml 2016-04-04 05:58:43.000000000 -0400
+++ temp/native-64/Xamarin.iOS.xml 2016-04-04 05:58:43.000000000 -0400
@@ -164415,14 +164415,14 @@
</class>
<class name="MidiValueMap" type="struct" base="System.ValueType" sealed="true" charset="Ansi" layout="Sequential">
<fields>
- <field name="Value" attrib="6" fieldtype="CoreMidi.MidiValueMap+[Value]__FixedBuffer0">
+ <field name="Value" attrib="6" fieldtype="CoreMidi.MidiValueMap+[Value]__FixedBuffer1">
<attributes>
<attribute name="System.Runtime.CompilerServices.FixedBufferAttribute" />
</attributes>
</field>
</fields>
<classes>
- <class name="&lt;Value&gt;__FixedBuffer0" type="struct" base="System.ValueType" sealed="true" charset="Ansi" layout="Sequential" pack="0" size="128">
+ <class name="&lt;Value&gt;__FixedBuffer1" type="struct" base="System.ValueType" sealed="true" charset="Ansi" layout="Sequential" pack="0" size="128">
<attributes>
<attribute name="System.Runtime.CompilerServices.CompilerGeneratedAttribute" />
<attribute name="System.Runtime.CompilerServices.UnsafeValueTypeAttribute" />
make[3]: *** [verify-reference-assemblies-ios] Error 1
diff --git a/src/CoreMidi/MidiThruConnectionParams.cs b/src/CoreMidi/MidiThruConnectionParams.cs
index 884693a..911cdcf 100644
--- a/src/CoreMidi/MidiThruConnectionParams.cs
+++ b/src/CoreMidi/MidiThruConnectionParams.cs
@@ -51,7 +51,7 @@ namespace XamCore.CoreMidi {
[StructLayout (LayoutKind.Sequential)]
public unsafe struct MidiValueMap {
- public fixed byte Value[128];
+ public byte[] Value;
}
[StructLayout (LayoutKind.Sequential)]
@@ -253,7 +253,6 @@ namespace XamCore.CoreMidi {
// Put ourselves at the end of the static struct in case we need to fetch the dynamic part of the struct
IntPtr bufferEnd = IntPtr.Add (buffer, Marshal.SizeOf (typeof (MidiThruConnectionParamsStruct)));
var controlsSize = Marshal.SizeOf (typeof (MidiControlTransform));
- var mapsSize = Marshal.SizeOf (typeof (MidiValueMap));
if (connectionParams.NumControlTransforms == 0)
Controls = null;
@@ -271,8 +270,11 @@ namespace XamCore.CoreMidi {
Maps = new MidiValueMap [connectionParams.NumMaps];
bufferEnd = IntPtr.Add (bufferEnd, controlsSize * connectionParams.NumControlTransforms);
unsafe { // Lets use memcpy to avoid a for loop
- fixed (MidiValueMap* arrAddr = &Maps[0])
- Runtime.memcpy ((IntPtr) arrAddr, bufferEnd, mapsSize * connectionParams.NumMaps);
+ for (int i = 0; i < connectionParams.NumMaps; i++) {
+ Maps [i].Value = new byte [128];
+ fixed (byte* arrAddr = &Maps[i].Value [0])
+ Runtime.memcpy ((IntPtr) arrAddr, bufferEnd, 128);
+ }
}
}
}
@@ -301,11 +303,10 @@ namespace XamCore.CoreMidi {
var paramsSize = Marshal.SizeOf (typeof (MidiThruConnectionParamsStruct));
var controlsSize = Marshal.SizeOf (typeof (MidiControlTransform));
- var mapsSize = Marshal.SizeOf (typeof (MidiValueMap));
// Get the full size of the struct, static + dynamic parts
var fullSize = paramsSize +
(Controls == null ? 0 : controlsSize * Controls.Length) +
- (Maps == null ? 0 : mapsSize * Maps.Length);
+ (Maps == null ? 0 : 128 * Maps.Length);
var buffer = Marshal.AllocHGlobal (fullSize);
var bufferEnd = IntPtr.Add (buffer, Marshal.SizeOf (typeof (MidiThruConnectionParamsStruct)));
@@ -324,8 +325,10 @@ namespace XamCore.CoreMidi {
// Set the destination buffer after controls arr if any
bufferEnd = IntPtr.Add (bufferEnd, controlsSize * connectionParams.NumControlTransforms);
unsafe { // Lets use memcpy to avoid a for loop
- fixed (MidiValueMap* arrAddr = &Maps[0])
- Runtime.memcpy (bufferEnd, (IntPtr) arrAddr, mapsSize * connectionParams.NumMaps);
+ for (int i = 0; i < connectionParams.NumMaps; i++) {
+ fixed (byte* arrAddr = &Maps[i].Value [0])
+ Runtime.memcpy (bufferEnd, (IntPtr) arrAddr, 128);
+ }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment