diff --git a/src/SFML.Audio/Music.cs b/src/SFML.Audio/Music.cs index b9dbfdd5..18992992 100644 --- a/src/SFML.Audio/Music.cs +++ b/src/SFML.Audio/Music.cs @@ -49,6 +49,8 @@ public Music(string filename) : public Music(Stream stream) : base(IntPtr.Zero) { + // Stream needs to stay alive as long as the Music instance is alive + // Disposing of it can only be done in Music's Dispose method _stream = new StreamAdaptor(stream); CPointer = sfMusic_createFromStream(_stream.InputStreamPtr); @@ -74,16 +76,14 @@ public Music(Stream stream) : public Music(byte[] bytes) : base(IntPtr.Zero) { - unsafe - { - fixed (void* ptr = bytes) - { - CPointer = sfMusic_createFromMemory((IntPtr)ptr, (UIntPtr)bytes.Length); - } - } + // Memory needs to stay pinned as long as the Music instance is alive + // Freeing the handle can only be done in Music's Dispose method + _bytesPin = GCHandle.Alloc(bytes, GCHandleType.Pinned); + CPointer = sfMusic_createFromMemory(_bytesPin.AddrOfPinnedObject(), (UIntPtr)bytes.Length); if (IsInvalid) { + _bytesPin.Free(); throw new LoadingFailedException("music"); } } @@ -555,10 +555,16 @@ protected override void Destroy(bool disposing) _stream?.Dispose(); } + if (_bytesPin.IsAllocated) + { + _bytesPin.Free(); + } + sfMusic_destroy(CPointer); } private readonly StreamAdaptor _stream; + private GCHandle _bytesPin; private EffectProcessorInternal _effectProcessor; /// diff --git a/src/SFML.Graphics/Font.cs b/src/SFML.Graphics/Font.cs index ee89c707..1628bb1a 100644 --- a/src/SFML.Graphics/Font.cs +++ b/src/SFML.Graphics/Font.cs @@ -41,10 +41,10 @@ public Font(string filename) : base(sfFont_createFromFile(filename)) //////////////////////////////////////////////////////////// public Font(Stream stream) : base(IntPtr.Zero) { - using (var adaptor = new StreamAdaptor(stream)) - { - CPointer = sfFont_createFromStream(adaptor.InputStreamPtr); - } + // Stream needs to stay alive as long as the Font instance is alive + // Disposing of it can only be done in Font's Dispose method + _myStream = new StreamAdaptor(stream); + CPointer = sfFont_createFromStream(_myStream.InputStreamPtr); if (IsInvalid) { @@ -62,16 +62,14 @@ public Font(Stream stream) : base(IntPtr.Zero) public Font(byte[] bytes) : base(IntPtr.Zero) { - unsafe - { - fixed (void* ptr = bytes) - { - CPointer = sfFont_createFromMemory((IntPtr)ptr, (UIntPtr)bytes.Length); - } - } + // Memory needs to stay pinned as long as the Font instance is alive + // Freeing the handle can only be done in Font's Dispose method + _myBytesPin = GCHandle.Alloc(bytes, GCHandleType.Pinned); + CPointer = sfFont_createFromMemory(_myBytesPin.AddrOfPinnedObject(), (UIntPtr)bytes.Length); if (IsInvalid) { + _myBytesPin.Free(); throw new LoadingFailedException("font"); } } @@ -245,6 +243,13 @@ protected override void Destroy(bool disposing) { texture.Dispose(); } + + _myStream?.Dispose(); + } + + if (_myBytesPin.IsAllocated) + { + _myBytesPin.Free(); } if (!disposing) @@ -285,6 +290,8 @@ internal struct InfoMarshalData } private readonly Dictionary _textures = new Dictionary(); + private readonly StreamAdaptor _myStream; + private GCHandle _myBytesPin; #region Imports [DllImport(CSFML.Graphics, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]