Made Callbacks a public field in StbiStreamWrapper.cs
All checks were successful
Build / build (push) Successful in 1m55s

This commit is contained in:
H. Utku Maden 2024-11-18 20:47:28 +03:00
parent 6ffcd38cbc
commit cb75b7c244
3 changed files with 26 additions and 33 deletions

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

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

@ -32,11 +32,12 @@ namespace ReFuel.Stb
public unsafe delegate int StbiEofProc(void *userdata); public unsafe delegate int StbiEofProc(void *userdata);
/// <summary> /// <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> /// </summary>
public unsafe class StbiStreamWrapper : IDisposable public unsafe class StbiStreamWrapper : IDisposable
{ {
private readonly stbi_io_callbacks _callbacks; public readonly stbi_io_callbacks Callbacks;
private readonly Stream _stream; private readonly Stream _stream;
private readonly bool _keepOpen; private readonly bool _keepOpen;
private bool _isDisposed; private bool _isDisposed;
@ -45,8 +46,6 @@ namespace ReFuel.Stb
private StbiSkipProc _skipCb; private StbiSkipProc _skipCb;
private StbiEofProc _eofCb; private StbiEofProc _eofCb;
public ref readonly stbi_io_callbacks Callbacks => ref _callbacks;
public StbiStreamWrapper(Stream stream, bool keepOpen = false) public StbiStreamWrapper(Stream stream, bool keepOpen = false)
{ {
if (stream == null) throw new ArgumentNullException(nameof(stream)); if (stream == null) throw new ArgumentNullException(nameof(stream));
@ -58,18 +57,10 @@ namespace ReFuel.Stb
_skipCb = SkipCb; _skipCb = SkipCb;
_eofCb = EofCb; _eofCb = EofCb;
_callbacks = default; Callbacks = default;
_callbacks.read = Marshal.GetFunctionPointerForDelegate<StbiReadProc>(_readCb); Callbacks.read = Marshal.GetFunctionPointerForDelegate<StbiReadProc>(_readCb);
_callbacks.skip = Marshal.GetFunctionPointerForDelegate<StbiSkipProc>(_skipCb); Callbacks.skip = Marshal.GetFunctionPointerForDelegate<StbiSkipProc>(_skipCb);
_callbacks.eof = Marshal.GetFunctionPointerForDelegate<StbiEofProc>(_eofCb); 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) private int ReadCb(void *userdata, byte* buffer, int count)