Compare commits

..

No commits in common. "master" and "v2.0.2-rc.1" have entirely different histories.

3 changed files with 33 additions and 26 deletions

View File

@ -14,7 +14,7 @@
<!-- Nuget Properties. -->
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>ReFuel.StbImage</PackageId>
<Version>2.1.0</Version>
<Version>2.0.2-rc.1</Version>
<Authors>STBI Authors, H. Utku Maden</Authors>
<Description>
A C# wrapper for the ubiquitous stb_image.h and stb_image_write.h library.
@ -26,10 +26,10 @@
<RepositoryUrl>https://git.mixedup.dev/ReFuel/ReFuel.StbImage</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>stb; stb_image; stbi; image; load; save; read; write</PackageTags>
<PackageReleaseNotes># 2.1.0 (ABI BRAKING)
<PackageReleaseNotes># 2.0.2
* Fixed calling convention of unmanaged function pointers. (Thanks NogginBops!)
* Modified StbiStreamWrapper in order to fixed backing delegates of function pointers from being prematurely collected
by release mode JIT and the GC. StbiStreamWrapper.Callbacks is now a readonly field. (ABI BREAKING)
* Allocating a GC handle to StbiStreamWrapper class and passing it as userdata into stbi in order to prevent
the object from being prematurely collected by the garbage collector when optimizations are enabled in Release mode.
# 2.0.1
* Enabled optimizations across the board for native and managed assemblies.
@ -56,7 +56,7 @@
<Content Include="runtimes/linux-arm64/native/*.so">
<PackagePath>runtimes/linux-arm64/native/</PackagePath>
<Pack>true</Pack>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest/</CopyToOutputDirectory>
</Content>
<Content Include="runtimes/linux-x64/native/*.so">
<PackagePath>runtimes/linux-x64/native/</PackagePath>

View File

@ -209,19 +209,19 @@ namespace ReFuel.Stb
{
int x, y, iFormat;
StbiStreamWrapper wrapper = new StbiStreamWrapper(stream, true);
GCHandle gch = GCHandle.Alloc(wrapper, GCHandleType.Normal);
wrapper.CreateCallbacks(out stbi_io_callbacks cb);
stream.Position = 0;
IntPtr imagePtr;
fixed (stbi_io_callbacks* cb = &wrapper.Callbacks)
if (asFloat)
{
if (asFloat)
{
imagePtr = (IntPtr)Stbi.loadf_from_callbacks(cb, null, &x, &y, &iFormat, (int)format);
}
else
{
imagePtr = (IntPtr)Stbi.load_from_callbacks(cb, null, &x, &y, &iFormat, (int)format);
}
imagePtr = (IntPtr)Stbi.loadf_from_callbacks(&cb, (void*)(IntPtr)gch, &x, &y, &iFormat, (int)format);
}
else
{
imagePtr = (IntPtr)Stbi.load_from_callbacks(&cb, (void*)(IntPtr)gch, &x, &y, &iFormat, (int)format);
}
gch.Free();
if (imagePtr != IntPtr.Zero)
{
@ -319,12 +319,10 @@ namespace ReFuel.Stb
{
int x, y, iFormat;
StbiStreamWrapper wrapper = new StbiStreamWrapper(stream, true);
int result;
wrapper.CreateCallbacks(out stbi_io_callbacks cb);
stream.Position = 0;
fixed (stbi_io_callbacks* cb = &wrapper.Callbacks)
{
result = Stbi.info_from_callbacks(cb, null, &x, &y, &iFormat);
}
int result = Stbi.info_from_callbacks(&cb, null, &x, &y, &iFormat);
width = x;
height = y;

View File

@ -32,12 +32,11 @@ namespace ReFuel.Stb
public unsafe delegate int StbiEofProc(void *userdata);
/// <summary>
/// An easy-to-use stream wrapper for use with STBI image load functions.
/// An easy to use stream wrapper for use with STBI image load functions.
/// </summary>
public unsafe class StbiStreamWrapper : IDisposable
{
public readonly stbi_io_callbacks Callbacks;
private readonly stbi_io_callbacks _callbacks;
private readonly Stream _stream;
private readonly bool _keepOpen;
private bool _isDisposed;
@ -46,6 +45,8 @@ namespace ReFuel.Stb
private StbiSkipProc _skipCb;
private StbiEofProc _eofCb;
public ref readonly stbi_io_callbacks Callbacks => ref _callbacks;
public StbiStreamWrapper(Stream stream, bool keepOpen = false)
{
if (stream == null) throw new ArgumentNullException(nameof(stream));
@ -57,10 +58,18 @@ namespace ReFuel.Stb
_skipCb = SkipCb;
_eofCb = EofCb;
Callbacks = default;
Callbacks.read = Marshal.GetFunctionPointerForDelegate<StbiReadProc>(_readCb);
Callbacks.skip = Marshal.GetFunctionPointerForDelegate<StbiSkipProc>(_skipCb);
Callbacks.eof = Marshal.GetFunctionPointerForDelegate<StbiEofProc>(_eofCb);
_callbacks = default;
_callbacks.read = Marshal.GetFunctionPointerForDelegate<StbiReadProc>(_readCb);
_callbacks.skip = Marshal.GetFunctionPointerForDelegate<StbiSkipProc>(_skipCb);
_callbacks.eof = Marshal.GetFunctionPointerForDelegate<StbiEofProc>(_eofCb);
}
public void CreateCallbacks(out stbi_io_callbacks cb)
{
cb = default;
cb.read = Marshal.GetFunctionPointerForDelegate<StbiReadProc>(_readCb);
cb.skip = Marshal.GetFunctionPointerForDelegate<StbiSkipProc>(_skipCb);
cb.eof = Marshal.GetFunctionPointerForDelegate<StbiEofProc>(_eofCb);
}
private int ReadCb(void *userdata, byte* buffer, int count)