Skip to content

Use blittable byte for delegate callbacks and harden DelegateProxies - #5479

Open
mattleibow wants to merge 2 commits into
mainfrom
mattleibow-delegate-proxies-byte-returns-and-modern
Open

mattleibow wants to merge 2 commits into
mainfrom
mattleibow-delegate-proxies-byte-returns-and-modern

Conversation

@mattleibow

Copy link
Copy Markdown
Collaborator

Description

Eliminates non-blittable bool in generated native callback delegates (*ProxyDelegate), unmanaged function pointers (delegate* unmanaged[Cdecl]<...>), and DelegateProxies implementations, hardens SKManagedStream / SKManagedWStream reverse P/Invoke callbacks against uncaught managed exceptions, and simplifies DelegateProxies user-data and multi-delegate state storage:

  1. Generator & generated bindings (utils/SkiaSharpGenerator, binding/*/Generated):

    • bool is non-blittable in .NET, [MarshalAs(UnmanagedType.I1)] is ignored by [UnmanagedCallersOnly], and Mono's ARM64 interpreter (dotnet/runtime#136578) writes MONO_TYPE_BOOLEAN return values using a 1-byte strb that leaves bits 8..63 of x0/w0 dirty with the first argument pointer — breaking Apple ARM64 C++ bool callers (which emit cbz w0) as well as HarfBuzz hb_bool_t (typedef int hb_bool_t) callbacks.
    • GetManagedFunctionArguments and GetFunctionPointerType now map C bool and hb_bool_t (Boolean) to blittable Byte (byte) without [MarshalAs(UnmanagedType.I1)] on delegates or delegate proxy implementations, ensuring all 64 bits of x0/rax are zero-extended on return across RyuJIT and the Mono interpreter.
    • Updated the partial implementations in DelegateProxies.stream.cs, DelegateProxies.wstream.cs, DelegateProxies.cs (SKGraphiteImageProviderProxyImplementation), DelegateProxies.font.cs, and DelegateProxies.unicode.cs.
  2. Exception containment in DelegateProxies.stream.cs & DelegateProxies.wstream.cs:

    • Wrapped all 13 SKManagedStream*ProxyImplementation and all 4 SKManagedWStream*ProxyImplementation callbacks in try/catch (with if (gch.IsAllocated) gch.Free() in finally for Destroy) so exceptions thrown by an underlying .NET Stream cannot escape [UnmanagedCallersOnly] and abort the process (PAL_SEHException).
    • Recorded read/peek/seek callback exceptions on SKAbstractManagedStream (hasError) so subsequent SKManagedStreamIsAtEndProxyImplementation calls return 1 (true), ensuring native do { read(); } while (!isAtEnd()); loops terminate immediately even when OnIsAtEnd() itself does not throw (such as a disposed MemoryStream where CanSeek is false).
  3. DelegateProxies.shared.cs modernization:

    • Simplified CreateUserData / GetUserData so the GCHandle directly holds userData (or a WeakReference) rather than allocating a UserDataDelegate closure and invoking it on every callback.
    • Simplified CreateMulti / GetMulti and CreateMultiUserData / GetMultiUserData to store a lightweight MultiUserData state object instead of nested GetMultiDelegateDelegate + UserDataDelegate closures.

Related issues

Related to #3377

Required skia PR

None.

Areas affected

  • Managed API (binding/)
  • Native / C API (externals/skia/src/c, include/c)
  • Generated P/Invoke bindings
  • Native dependency or Skia update (libpng, HarfBuzz, FreeType, zlib, milestone bump, …)
  • Views & integrations (MAUI, Uno, WPF, WinUI, Blazor, …)
  • Rendering output / visual behavior
  • Performance
  • Tests
  • Build, packaging, or CI
  • Documentation or samples

Changes

Behavior

  • Native reverse-P/Invoke callbacks for SKAbstractManagedStream / SKManagedStream and SKAbstractManagedWStream / SKManagedWStream no longer allow managed exceptions from an underlying .NET Stream to escape [UnmanagedCallersOnly] and crash the process; failed reads mark the stream as at-end so native read-until-EOF loops terminate cleanly.
  • Generated native callback delegates and function pointers in SkiaSharp and HarfBuzzSharp use blittable byte instead of bool.

Testing

  • Regenerated bindings cleanly:
    • pwsh -NoLogo -NoProfile -File ./utils/generate.ps1 — passed
  • Built SkiaSharp and HarfBuzzSharp across all target frameworks:
    • dotnet build binding/SkiaSharp/SkiaSharp.csproj — passed (0 errors)
    • dotnet build binding/HarfBuzzSharp/HarfBuzzSharp.csproj — passed (0 errors)
  • Ran the full console test suite on macOS ARM64 (net10.0):
    • dotnet test tests/SkiaSharp.Tests.Console.slnx -p:TargetFramework=net10.0 -p:TargetFrameworks=net10.0 — passed (SkiaSharp.Tests: 6451 passed, 0 failed, 23 skipped; SkiaSharp.Gallery.Tests.Console: 50 passed, 0 failed; SkiaSharp.Tests.SingletonInit: 1 passed, 0 failed; SkiaSharp.Direct3D.Tests: 2 passed, 0 failed, 3 skipped; SkiaSharp.Vulkan.Tests: 4 passed, 0 failed, 21 skipped)
  • Added unit tests in SKManagedStreamTest, SKManagedWStreamTest, HBFontFuncsTest, and HBUnicodeFuncsTest.

Checklist

  • Tests added or updated (if omitted, explain why above)
  • Changes above lists all public API and behavioral changes (or "None.")
  • New/changed public API? Added or updated accurate source /// documentation and regenerated bindings when applicable
  • Native change? Companion mono/skia PR linked above and bindings regenerated

@github-actions

Copy link
Copy Markdown
Contributor

📖 Documentation Preview

Add the automation/staging label to build and publish a documentation preview for this PR.

Removing the label removes the preview. While the label is present, each new commit updates it.


This comment is automatically updated by the documentation staging workflow.

@github-actions

Copy link
Copy Markdown
Contributor

📦 Try the packages from this PR

Warning

Do not run these scripts without first reviewing the code in this PR.

Step 1 — Download the packages

bash / macOS / Linux:

curl -fsSL https://raw.githubusercontent.com/mono/SkiaSharp/main/scripts/get-skiasharp-pr.sh | bash -s -- 5479

PowerShell / Windows:

iex "& { $(irm https://raw.githubusercontent.com/mono/SkiaSharp/main/scripts/get-skiasharp-pr.ps1) } 5479"

Step 2 — Add the local NuGet source

dotnet nuget add source ~/.skiasharp/hives/pr-5479/packages --name skiasharp-pr-5479
More options
Option Description
--successful-only / -SuccessfulOnly Only use successful builds
--force / -Force Overwrite previously downloaded packages
--list / -List List available artifacts without downloading
--build-id ID / -BuildId ID Download from a specific build

Or download manually from Azure Pipelines — look for the nuget artifact on the build for this PR.

Remove the source when you're done:

dotnet nuget remove source skiasharp-pr-5479

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

📊 SkiaSharp benchmarks — PR #5479

⭐ this PR (full source build) vs 🌙 nightly · Linux · Windows · macOS

Informational only — this never blocks the PR. 🟢 faster / less allocation · 🔴 slower / more allocation; moves under 5% are hidden as noise.

⏱️ Times are raw BenchmarkDotNet means, and the ⭐ PR and baseline legs run on separate CI runners, so microbenchmarks can swing run-to-run — treat small time deltas as noise. Allocations are deterministic and the reliable signal. The interactive perf-dashboard (linked below) applies smoothing for the trend view.

Highlights

⏱️ Time — 🔴 56 slower · 🟢 25 faster

  • 🔴 PathBoundsBenchmark.TightBounds(Points: 1024) · Windows · 15.22 µs → 21.33 µs (+40%)
  • 🔴 MatrixMapPointsBenchmark.MapRect(Points: 4096) · macOS · 54.32 µs → 76.07 µs (+40%)
  • 🔴 RasterImageLifecycleBenchmark.CreateDataWithReleaseProc(Count: 256) · Windows · 96.67 µs → 131.37 µs (+36%)
  • 🔴 MatrixMapPointsBenchmark.MapRadius(Points: 4096) · Windows · 136.27 µs → 182.27 µs (+34%)
  • 🔴 MatrixMapPointsBenchmark.MapRadius(Points: 256) · Windows · 8.50 µs → 11.13 µs (+31%)
  • …and 76 more (see details below)
Full per-OS benchmark deltas

Linux

⏱️ Time (vs 🌙 nightly 4.156.0-nightly.26527.6)

Benchmark baseline this PR Δ
MatrixOpsBenchmark.Invert(Count: 4096) 149.10 µs 127.37 µs 🟢 -15%
MatrixMapPointsBenchmark.MapRect(Points: 4096) 204.55 µs 176.58 µs 🟢 -14%
MatrixMapPointsBenchmark.MapRect(Points: 256) 12.69 µs 11.02 µs 🟢 -13%
RasterImageLifecycleBenchmark.CreateDataWithReleaseProc(Count: 256) 96.90 µs 108.25 µs 🔴 +12%
ColorMathBenchmark.PreMultiply(Colors: 4096) 14.50 µs 12.87 µs 🟢 -11%
MatrixMapPointsBenchmark.MapRadius(Points: 4096) 243.55 µs 217.46 µs 🟢 -11%
MatrixMapPointsBenchmark.MapRadius(Points: 256) 15.14 µs 13.59 µs 🟢 -10%
MatrixOpsBenchmark.Concat(Count: 4096) 241.84 µs 217.21 µs 🟢 -10%
MatrixMapPointsBenchmark.MapPoints(Points: 4096) 2.48 µs 2.72 µs 🔴 +10%
PathBoundsBenchmark.TightBounds(Points: 1024) 11.09 µs 10.06 µs 🟢 -9%
MatrixMapPointsBenchmark.MapVector(Points: 4096) 190.95 µs 173.75 µs 🟢 -9%
LargeImageScaleBenchmark.UpscaleOpaque(Size: 1024) 747.07 µs 683.88 µs 🟢 -8%
MatrixMapPointsBenchmark.MapPoint(Points: 4096) 79.85 µs 73.44 µs 🟢 -8%
MatrixMapPointsBenchmark.MapPoint(Points: 256) 4.99 µs 4.60 µs 🟢 -8%
MatrixMapPointsBenchmark.MapVector(Points: 256) 11.74 µs 10.84 µs 🟢 -8%
LargeImageScaleBenchmark.UpscaleOpaque(Size: 2048) 2.86 ms 2.64 ms 🟢 -8%
BitmapDrawBenchmark.DrawScaledTiles(Tiles: 64) 377.41 µs 350.58 µs 🟢 -7%
ColorMathBenchmark.UnPreMultiply(Colors: 4096) 12.97 µs 12.12 µs 🟢 -7%
ColorMathBenchmark.ToColorF(Colors: 4096) 14.01 µs 13.12 µs 🟢 -6%
RuntimeEffectShaderBenchmark.DrawFrame 3.02 ms 2.83 ms 🟢 -6%
LargeImageScaleBenchmark.UpscaleCrossfade(Size: 2048) 8.09 ms 7.63 ms 🟢 -6%
CanvasDrawBenchmark.Draw(Shapes: 512) 35.23 ms 33.26 ms 🟢 -6%
RasterImageLifecycleBenchmark.CreateRasterImage(Count: 256) 256.42 µs 270.11 µs 🔴 +5%
CanvasDrawBenchmark.Draw(Shapes: 64) 4.40 ms 4.17 ms 🟢 -5%
MatrixMapPointsBenchmark.MapPoints(Points: 256) 209.0 ns 219.6 ns 🔴 +5%

Windows

⏱️ Time (vs 🌙 nightly 4.156.0-nightly.26527.6)

Benchmark baseline this PR Δ
PathBoundsBenchmark.TightBounds(Points: 1024) 15.22 µs 21.33 µs 🔴 +40%
RasterImageLifecycleBenchmark.CreateDataWithReleaseProc(Count: 256) 96.67 µs 131.37 µs 🔴 +36%
MatrixMapPointsBenchmark.MapRadius(Points: 4096) 136.27 µs 182.27 µs 🔴 +34%
MatrixMapPointsBenchmark.MapRadius(Points: 256) 8.50 µs 11.13 µs 🔴 +31%
PathBoundsBenchmark.TightBounds(Points: 64) 1.50 µs 1.95 µs 🔴 +30%
MatrixOpsBenchmark.Concat(Count: 4096) 217.07 µs 273.82 µs 🔴 +26%
RasterImageLifecycleBenchmark.CreateRasterImage(Count: 256) 248.27 µs 311.04 µs 🔴 +25%
MatrixMapPointsBenchmark.MapPoints(Points: 256) 182.5 ns 220.5 ns 🔴 +21%
MatrixMapPointsBenchmark.MapVector(Points: 256) 7.62 µs 9.17 µs 🔴 +20%
MatrixMapPointsBenchmark.MapVector(Points: 4096) 122.23 µs 146.70 µs 🔴 +20%
MatrixOpsBenchmark.Invert(Count: 4096) 127.60 µs 153.12 µs 🔴 +20%
MatrixMapPointsBenchmark.MapRect(Points: 4096) 167.13 µs 199.37 µs 🔴 +19%
MatrixMapPointsBenchmark.MapRect(Points: 256) 10.42 µs 12.39 µs 🔴 +19%
ColorParseBenchmark.Parse(Iterations: 1000) 75.13 µs 86.30 µs 🔴 +15%
MatrixMapPointsBenchmark.MapPoints(Points: 4096) 2.62 µs 2.23 µs 🟢 -15%
BitmapDrawBenchmark.DrawScaledTiles(Tiles: 64) 322.41 µs 365.34 µs 🔴 +13%
ColorMathBenchmark.PreMultiply(Colors: 4096) 13.00 µs 14.67 µs 🔴 +13%
ColorMathBenchmark.UnPreMultiply(Colors: 4096) 11.46 µs 12.93 µs 🔴 +13%
CanvasDrawBenchmark.Draw(Shapes: 512) 20.88 ms 23.42 ms 🔴 +12%
ColorMathBenchmark.ToColor(Colors: 4096) 14.46 µs 16.20 µs 🔴 +12%
RuntimeEffectShaderBenchmark.DrawFrame 1.13 ms 1.26 ms 🔴 +11%
BitmapDrawBenchmark.DrawUnscaledTiles(Tiles: 64) 245.68 µs 273.41 µs 🔴 +11%
BitmapDrawBenchmark.DrawScaledTiles(Tiles: 256) 1.24 ms 1.37 ms 🔴 +11%
LargeImageScaleBenchmark.UpscaleOpaque(Size: 2048) 2.90 ms 3.21 ms 🔴 +11%
CanvasDrawBenchmark.Draw(Shapes: 64) 2.66 ms 2.93 ms 🔴 +10%
…and 6 more

macOS

⏱️ Time (vs 🌙 nightly 4.156.0-nightly.26527.6)

Benchmark baseline this PR Δ
MatrixMapPointsBenchmark.MapRect(Points: 4096) 54.32 µs 76.07 µs 🔴 +40%
MatrixMapPointsBenchmark.MapPoints(Points: 256) 155.4 ns 199.2 ns 🔴 +28%
MatrixMapPointsBenchmark.MapPoints(Points: 4096) 1.73 µs 2.16 µs 🔴 +25%
ColorParseBenchmark.Parse(Iterations: 1000) 73.95 µs 89.55 µs 🔴 +21%
BitmapDrawBenchmark.DrawScaledTiles(Tiles: 64) 342.27 µs 274.64 µs 🟢 -20%
MatrixMapPointsBenchmark.MapPoint(Points: 4096) 21.15 µs 24.84 µs 🔴 +17%
BitmapDrawBenchmark.DrawUnscaledTiles(Tiles: 64) 223.08 µs 261.83 µs 🔴 +17%
RasterImageLifecycleBenchmark.CreateRasterImage(Count: 256) 155.12 µs 180.76 µs 🔴 +17%
LargeImageScaleBenchmark.UpscaleCrossfade(Size: 2048) 6.65 ms 7.56 ms 🔴 +14%
ColorMathBenchmark.PreMultiply(Colors: 4096) 9.09 µs 10.31 µs 🔴 +13%
MatrixOpsBenchmark.Concat(Count: 4096) 119.31 µs 133.99 µs 🔴 +12%
CanvasDrawBenchmark.Draw(Shapes: 64) 2.45 ms 2.17 ms 🟢 -11%
MatrixMapPointsBenchmark.MapRadius(Points: 256) 6.72 µs 7.40 µs 🔴 +10%
SceneRenderBenchmark.RenderFrame(Complexity: 1) 1.32 ms 1.45 ms 🔴 +10%
MatrixMapPointsBenchmark.MapRect(Points: 256) 3.35 µs 3.68 µs 🔴 +10%
RasterImageLifecycleBenchmark.CreateDataWithReleaseProc(Count: 256) 78.84 µs 86.31 µs 🔴 +9%
CanvasDrawBenchmark.Draw(Shapes: 512) 17.93 ms 16.65 ms 🟢 -7%
MatrixMapPointsBenchmark.MapVector(Points: 4096) 43.81 µs 46.88 µs 🔴 +7%
LargeImageScaleBenchmark.UpscaleCrossfade(Size: 1024) 1.59 ms 1.70 ms 🔴 +7%
ColorMathBenchmark.UnPreMultiply(Colors: 4096) 8.90 µs 9.50 µs 🔴 +7%
PathBoundsBenchmark.TightBounds(Points: 64) 980.1 ns 1.04 µs 🔴 +7%
ColorMathBenchmark.ToColorF(Colors: 4096) 6.14 µs 6.54 µs 🔴 +6%
PathBoundsBenchmark.TightBounds(Points: 1024) 9.28 µs 9.86 µs 🔴 +6%
LargeImageScaleBenchmark.UpscaleOpaque(Size: 1024) 766.45 µs 813.51 µs 🔴 +6%
MatrixMapPointsBenchmark.MapPoint(Points: 256) 1.32 µs 1.38 µs 🔴 +5%

📈 Full interactive perf-dashboard & run details →

@mattleibow
mattleibow requested a balanced review from Copilot October 28, 2026 17:16
@mattleibow

Copy link
Copy Markdown
Collaborator Author

@dalexsoto review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The tests do not cover recovery after callback exceptions, leaving error-state resets on successful Rewind/Seek/Move and preservation on failed repositioning unverified.

1 open issue
What changed in this PR

This PR hardens SkiaSharp and HarfBuzzSharp native callbacks by replacing callback bool values with blittable bytes, containing managed stream exceptions, and simplifying callback state storage.

Changes:

  • Updates the generator, generated callback signatures, and proxy implementations to use byte.
  • Adds stream exception containment and error-state tracking, with regression tests for stream failures and false-returning HarfBuzz callbacks.
  • Replaces closure-based callback state with direct user-data handles and a shared state object.
File Description
utils/​SkiaSharpGenerator/​Generate/​Generator.cs Removes callback boolean marshalling attributes.
utils/​SkiaSharpGenerator/​BaseTool.cs Maps callback booleans to bytes.
tests/​Tests/​SkiaSharp/​SKManagedWStreamTest.cs Tests throwing write-stream callbacks.
tests/​Tests/​SkiaSharp/​SKManagedStreamTest.cs Tests callback failures and disposed-stream termination.
tests/​Tests/​HarfBuzzSharp/​HBUnicodeFuncsTest.cs Tests false-returning Unicode callbacks.
tests/​Tests/​HarfBuzzSharp/​HBFontFuncsTest.cs Tests false-returning font callbacks.
binding/​SkiaSharp/​SKAbstractManagedStream.cs Adds callback error-state storage.
binding/​SkiaSharp/​Generated/​SKManagedWStreamWriteProxyDelegate.generated.cs Changes write delegate return to byte.
binding/​SkiaSharp/​Generated/​SKManagedWStreamDelegates.generated.cs Updates write function-pointer signature.
binding/​SkiaSharp/​Generated/​SKManagedStreamSeekProxyDelegate.generated.cs Changes seek delegate return to byte.
binding/​SkiaSharp/​Generated/​SKManagedStreamRewindProxyDelegate.generated.cs Changes rewind delegate return to byte.
binding/​SkiaSharp/​Generated/​SKManagedStreamMoveProxyDelegate.generated.cs Changes move delegate return to byte.
binding/​SkiaSharp/​Generated/​SKManagedStreamIsAtEndProxyDelegate.generated.cs Changes EOF delegate return to byte.
binding/​SkiaSharp/​Generated/​SKManagedStreamHasPositionProxyDelegate.generated.cs Changes position-capability return to byte.
binding/​SkiaSharp/​Generated/​SKManagedStreamHasLengthProxyDelegate.generated.cs Changes length-capability return to byte.
binding/​SkiaSharp/​Generated/​SKManagedStreamDelegates.generated.cs Updates stream function-pointer signatures.
binding/​SkiaSharp/​Generated/​SKGraphiteImageProviderProxyDelegate.generated.cs Changes mipmapping parameter to byte.
binding/​SkiaSharp/​Generated/​DelegateProxies_SKManagedWStreamWriteProxyDelegate.generated.cs Updates write proxy declarations.
binding/​SkiaSharp/​Generated/​DelegateProxies_SKManagedStreamSeekProxyDelegate.generated.cs Updates seek proxy declarations.
binding/​SkiaSharp/​Generated/​DelegateProxies_SKManagedStreamRewindProxyDelegate.generated.cs Updates rewind proxy declarations.
binding/​SkiaSharp/​Generated/​DelegateProxies_SKManagedStreamMoveProxyDelegate.generated.cs Updates move proxy declarations.
binding/​SkiaSharp/​Generated/​DelegateProxies_SKManagedStreamIsAtEndProxyDelegate.generated.cs Updates EOF proxy declarations.
binding/​SkiaSharp/​Generated/​DelegateProxies_SKManagedStreamHasPositionProxyDelegate.generated.cs Updates position-capability proxy declarations.
binding/​SkiaSharp/​Generated/​DelegateProxies_SKManagedStreamHasLengthProxyDelegate.generated.cs Updates length-capability proxy declarations.
binding/​SkiaSharp/​Generated/​DelegateProxies_SKGraphiteImageProviderProxyDelegate.generated.cs Updates image-provider proxy declarations.
binding/​SkiaSharp/​DelegateProxies.wstream.cs Contains write-stream callback exceptions.
binding/​SkiaSharp/​DelegateProxies.stream.cs Contains exceptions and tracks stream error recovery.
binding/​SkiaSharp/​DelegateProxies.cs Converts mipmapping byte to managed boolean.
binding/​HarfBuzzSharp/​Generated/​UnicodeDecomposeProxyDelegate.generated.cs Changes decomposition return to byte.
binding/​HarfBuzzSharp/​Generated/​UnicodeComposeProxyDelegate.generated.cs Changes composition return to byte.
binding/​HarfBuzzSharp/​Generated/​FontGetVariationGlyphProxyDelegate.generated.cs Changes variation-glyph return to byte.
binding/​HarfBuzzSharp/​Generated/​FontGetNominalGlyphProxyDelegate.generated.cs Changes nominal-glyph return to byte.
binding/​HarfBuzzSharp/​Generated/​FontGetGlyphProxyDelegate.generated.cs Changes glyph lookup return to byte.
binding/​HarfBuzzSharp/​Generated/​FontGetGlyphOriginProxyDelegate.generated.cs Changes glyph-origin return to byte.
binding/​HarfBuzzSharp/​Generated/​FontGetGlyphNameProxyDelegate.generated.cs Changes glyph-name return to byte.
binding/​HarfBuzzSharp/​Generated/​FontGetGlyphFromNameProxyDelegate.generated.cs Changes name lookup return to byte.
binding/​HarfBuzzSharp/​Generated/​FontGetGlyphExtentsProxyDelegate.generated.cs Changes glyph-extents return to byte.
binding/​HarfBuzzSharp/​Generated/​FontGetGlyphContourPointProxyDelegate.generated.cs Changes contour-point return to byte.
binding/​HarfBuzzSharp/​Generated/​FontGetFontExtentsProxyDelegate.generated.cs Changes font-extents return to byte.
binding/​HarfBuzzSharp/​Generated/​DelegateProxies_UnicodeDecomposeProxyDelegate.generated.cs Updates decomposition proxy declarations.
binding/​HarfBuzzSharp/​Generated/​DelegateProxies_UnicodeComposeProxyDelegate.generated.cs Updates composition proxy declarations.
binding/​HarfBuzzSharp/​Generated/​DelegateProxies_FontGetVariationGlyphProxyDelegate.generated.cs Updates variation-glyph proxy declarations.
binding/​HarfBuzzSharp/​Generated/​DelegateProxies_FontGetNominalGlyphProxyDelegate.generated.cs Updates nominal-glyph proxy declarations.
binding/​HarfBuzzSharp/​Generated/​DelegateProxies_FontGetGlyphOriginProxyDelegate.generated.cs Updates glyph-origin proxy declarations.
binding/​HarfBuzzSharp/​Generated/​DelegateProxies_FontGetGlyphNameProxyDelegate.generated.cs Updates glyph-name proxy declarations.
binding/​HarfBuzzSharp/​Generated/​DelegateProxies_FontGetGlyphFromNameProxyDelegate.generated.cs Updates name lookup proxy declarations.
binding/​HarfBuzzSharp/​Generated/​DelegateProxies_FontGetGlyphExtentsProxyDelegate.generated.cs Updates glyph-extents proxy declarations.
binding/​HarfBuzzSharp/​Generated/​DelegateProxies_FontGetGlyphContourPointProxyDelegate.generated.cs Updates contour-point proxy declarations.
binding/​HarfBuzzSharp/​Generated/​DelegateProxies_FontGetFontExtentsProxyDelegate.generated.cs Updates font-extents proxy declarations.
binding/​HarfBuzzSharp/​Generated/​BufferMessageProxyDelegate.generated.cs Changes buffer-message return to byte.
binding/​HarfBuzzSharp/​DelegateProxies.unicode.cs Converts Unicode callback results to bytes.
binding/​HarfBuzzSharp/​DelegateProxies.font.cs Converts font results and short-circuits failed name lookups.
binding/​Binding.Shared/​DelegateProxies.shared.cs Replaces closures with direct callback state storage.

Review effort: Balanced

Comment thread binding/SkiaSharp/DelegateProxies.stream.cs
Copilot AI added 2 commits October 28, 2026 19:43
- Update SkiaSharpGenerator to emit blittable Byte instead of bool
  (and omit [MarshalAs(UnmanagedType.I1)]) for generated delegate types,
  unmanaged function pointers, and DelegateProxies implementations,
  avoiding non-blittable bool return ABI issues under [UnmanagedCallersOnly]
  and Mono's ARM64 interpreter (dotnet/runtime#136578).
- Wrap SKManagedStream and SKManagedWStream proxy callbacks in try/catch/finally
  so exceptions from underlying .NET Streams cannot escape [UnmanagedCallersOnly]
  and abort the process, and mark the stream as at-end on read/seek failures
  so native read-until-EOF loops terminate immediately.
- Simplify DelegateProxies.CreateUserData/GetUserData and CreateMulti/CreateMultiUserData
  to store userData or a MultiUserData state object directly in the GCHandle
  instead of allocating and invoking nested closure delegates on every callback.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…overy

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@mattleibow
mattleibow force-pushed the mattleibow-delegate-proxies-byte-returns-and-modern branch from baee8fe to 146011d Compare October 28, 2026 17:43

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants