Skip to content

Commit

Permalink
[CoreGraphics] Remove a CGPDFOperatorTable.SetCallback overload in .N…
Browse files Browse the repository at this point in the history
…ET. (dotnet#14219)

Remove the CGPDFOperatorTable.SetCallback overload that takes a normal managed
delegate, because on platforms that are AOT'ed, this delegate must point to a
static function with the MonoPInvokeCallback attribute, and if you don't
follow this requirement, you'll either get an exception at runtime (which is
not very nice to the app developer) or make the AOT compiler crash (which is a
completely different level of not being nice to developers).

In .NET, we already have an overload that takes an unmanaged function pointer,
where these requirements are enforced by the C# compiler, so just use that
instead.
  • Loading branch information
rolfbjarne authored and TJ Lambert committed Mar 8, 2022
1 parent 6fa0d61 commit 756e2db
Showing 1 changed file with 5 additions and 4 deletions.
9 changes: 5 additions & 4 deletions src/CoreGraphics/CGPDFOperatorTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,12 @@ protected override void Release ()
CGPDFOperatorTableRelease (GetCheckedHandle ());
}

#if !NET
// We need this P/Invoke for legacy AOT scenarios (since we have public API taking a 'Action<IntPtr, IntPtr>', and with this particular native function we can't wrap the delegate)
// Unfortunately CoreCLR doesn't support generic Action delegates in P/Invokes: https://github.com/dotnet/runtime/issues/32963
[DllImport (Constants.CoreGraphicsLibrary)]
extern static void CGPDFOperatorTableSetCallback (/* CGPDFOperatorTableRef */ IntPtr table, /* const char */ string name, /* CGPDFOperatorCallback */ Action<IntPtr,IntPtr>? callback);
#endif

#if NET
// This signature requires C# 9 (so .NET only).
Expand All @@ -77,7 +79,7 @@ protected override void Release ()
unsafe extern static void CGPDFOperatorTableSetCallback (/* CGPDFOperatorTableRef */ IntPtr table, /* const char */ string name, /* CGPDFOperatorCallback */ delegate* unmanaged<IntPtr, IntPtr, void> callback);
#endif

#if MONOMAC
#if MONOMAC && !NET
// This signature can work everywhere, but we can't enforce at compile time that 'callback' is a delegate to a static function (which is required for FullAOT scenarios),
// so limit it to non-FullAOT platforms (macOS)
[DllImport (Constants.CoreGraphicsLibrary)]
Expand All @@ -103,17 +105,16 @@ public void SetCallback (string name, Action<CGPDFScanner?,object?>? callback)
[Advice ("Use the nicer SetCallback(string,Action<CGPDFScanner,object>) API when possible.")]
#endif

#if !NET
// this API is ugly - but I do not see a better way with the AOT limitation
#if NET && !MONOMAC
[Obsolete ("Use the overload that takes a function pointer ('delegate*<IntPtr,IntPtr,void>') instead.")]
#endif
public void SetCallback (string name, Action<IntPtr,IntPtr>? callback)
{
if (name is null)
throw new ArgumentNullException (nameof (name));

CGPDFOperatorTableSetCallback (Handle, name, callback);
}
#endif // !NET

#if NET
// this signature requires C# 9 and unsafe code
Expand Down

0 comments on commit 756e2db

Please sign in to comment.