Skip to content

Commit

Permalink
[src] Refactor block code to use blittable callbacks. (#17641)
Browse files Browse the repository at this point in the history
This is mostly converting 'bool' arguments to 'byte' arguments, and 'string'
arguments to 'IntPtr' with custom utf8->string conversions.

This is necessary in order to convert all block callbacks to use
UnmanagedCallersOnly function pointers (which can't have non-blittable types
in their signature).

Contributes towards #15783.
  • Loading branch information
rolfbjarne authored Mar 1, 2023
1 parent 2178951 commit 967358c
Show file tree
Hide file tree
Showing 19 changed files with 120 additions and 103 deletions.
6 changes: 3 additions & 3 deletions src/AddressBook/ABAddressBook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,15 +200,15 @@ public void RequestAccess (Action<bool, NSError?> onCompleted)
}
}

internal delegate void InnerCompleted (IntPtr block, bool success, IntPtr error);
internal delegate void InnerCompleted (IntPtr block, byte success, IntPtr error);
static readonly InnerCompleted static_completionHandler = TrampolineCompletionHandler;
[MonoPInvokeCallback (typeof (InnerCompleted))]
static unsafe void TrampolineCompletionHandler (IntPtr block, bool success, IntPtr error)
static unsafe void TrampolineCompletionHandler (IntPtr block, byte success, IntPtr error)
{
var descriptor = (BlockLiteral*) block;
var del = descriptor->Target as Action<bool, NSError?>;
if (del is not null)
del (success, Runtime.GetNSObject<NSError> (error));
del (success != 0, Runtime.GetNSObject<NSError> (error));
}

[DllImport (Constants.AddressBookLibrary)]
Expand Down
12 changes: 7 additions & 5 deletions src/CoreGraphics/CGPDFArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,19 +218,21 @@ public bool GetString (int idx, out string? result)
}
#endif

delegate bool ApplyBlockHandlerDelegate (IntPtr block, nint index, IntPtr value, IntPtr info);
delegate byte ApplyBlockHandlerDelegate (IntPtr block, nint index, IntPtr value, IntPtr info);
static readonly ApplyBlockHandlerDelegate applyblock_handler = ApplyBlockHandler;

#if !MONOMAC
[MonoPInvokeCallback (typeof (ApplyBlockHandlerDelegate))]
#endif
static bool ApplyBlockHandler (IntPtr block, nint index, IntPtr value, IntPtr info)
static byte ApplyBlockHandler (IntPtr block, nint index, IntPtr value, IntPtr info)
{
var del = BlockLiteral.GetTarget<ApplyCallback> (block);
if (del is not null)
return del (index, CGPDFObject.FromHandle (value), info == IntPtr.Zero ? null : GCHandle.FromIntPtr (info).Target);
if (del is not null) {
var context = info == IntPtr.Zero ? null : GCHandle.FromIntPtr (info).Target;
return del (index, CGPDFObject.FromHandle (value), context) ? (byte) 1 : (byte) 0;
}

return false;
return 0;
}

public delegate bool ApplyCallback (nint index, object? value, object? info);
Expand Down
10 changes: 7 additions & 3 deletions src/CoreText/CTFontManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,18 @@ static NSArray EnsureNonNullArray (object [] items, string name)
#endif
public delegate bool CTFontRegistrationHandler (NSError [] errors, bool done);

internal delegate bool InnerRegistrationHandler (IntPtr block, IntPtr errors, bool done);
internal delegate byte InnerRegistrationHandler (IntPtr block, IntPtr errors, byte done);
static readonly InnerRegistrationHandler callback = TrampolineRegistrationHandler;

[MonoPInvokeCallback (typeof (InnerRegistrationHandler))]
static unsafe bool TrampolineRegistrationHandler (IntPtr block, /* NSArray */ IntPtr errors, bool done)
static unsafe byte TrampolineRegistrationHandler (IntPtr block, /* NSArray */ IntPtr errors, byte done)
{
var del = BlockLiteral.GetTarget<CTFontRegistrationHandler> (block);
return del is not null ? del (NSArray.ArrayFromHandle<NSError> (errors), done) : true;
if (del is null)
return 0;

var rv = del (NSArray.ArrayFromHandle<NSError> (errors), done == 0 ? false : true);
return rv ? (byte) 1 : (byte) 0;
}

#if NET
Expand Down
11 changes: 7 additions & 4 deletions src/CoreText/CTLine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ public nfloat GetOffsetForStringIndex (nint charIndex)
}

public delegate void CaretEdgeEnumerator (double offset, nint charIndex, bool leadingEdge, ref bool stop);
unsafe delegate void CaretEdgeEnumeratorProxy (IntPtr block, double offset, nint charIndex, [MarshalAs (UnmanagedType.I1)] bool leadingEdge, [MarshalAs (UnmanagedType.I1)] ref bool stop);
unsafe delegate void CaretEdgeEnumeratorProxy (IntPtr block, double offset, nint charIndex, byte leadingEdge, byte* stop);

#if NET
[SupportedOSPlatform ("ios9.0")]
Expand All @@ -225,11 +225,14 @@ public nfloat GetOffsetForStringIndex (nint charIndex)
static unsafe readonly CaretEdgeEnumeratorProxy static_enumerate = TrampolineEnumerate;

[MonoPInvokeCallback (typeof (CaretEdgeEnumeratorProxy))]
static void TrampolineEnumerate (IntPtr blockPtr, double offset, nint charIndex, bool leadingEdge, ref bool stop)
unsafe static void TrampolineEnumerate (IntPtr blockPtr, double offset, nint charIndex, byte leadingEdge, byte* stopPointer)
{
var del = BlockLiteral.GetTarget<CaretEdgeEnumerator> (blockPtr);
if (del is not null)
del (offset, charIndex, leadingEdge, ref stop);
if (del is not null) {
bool stop = *stopPointer != 0;
del (offset, charIndex, leadingEdge != 0, ref stop);
*stopPointer = stop ? (byte) 1 : (byte) 0;
}
}

#if NET
Expand Down
15 changes: 8 additions & 7 deletions src/ImageIO/CGImageAnimation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,22 +120,23 @@ public static CGImageAnimationStatus AnimateImage (NSData data, CGImageAnimation
// This class bridges native block invocations that call into C#
//
static internal class SDCGImageSourceAnimationBlock {
static internal readonly DCGImageSourceAnimationBlock Handler = Invoke;
unsafe static internal readonly DCGImageSourceAnimationBlock Handler = Invoke;

[MonoPInvokeCallback (typeof (DCGImageSourceAnimationBlock))]
static void Invoke (IntPtr block, nint index, IntPtr image, [MarshalAs (UnmanagedType.I1)] out bool stop)
internal unsafe static void Invoke (IntPtr block, nint index, IntPtr image, byte* stop)
{
var del = BlockLiteral.GetTarget<CGImageSourceAnimationHandler> (block);
if (del is not null)
del (index, new CoreGraphics.CGImage (image, false), out stop);
else
stop = false;
if (del is not null) {
del (index, new CoreGraphics.CGImage (image, false), out var stopValue);
*stop = stopValue ? (byte) 1 : (byte) 0;
} else
*stop = 0;
}
} /* class SDCGImageSourceAnimationBlock */

[UnmanagedFunctionPointerAttribute (CallingConvention.Cdecl)]
[UserDelegateType (typeof (CGImageSourceAnimationHandler))]
internal delegate void DCGImageSourceAnimationBlock (IntPtr block, nint index, IntPtr imageHandle, [MarshalAs (UnmanagedType.I1)] out bool stop);
unsafe internal delegate void DCGImageSourceAnimationBlock (IntPtr block, nint index, IntPtr imageHandle, byte* stop);
}

}
6 changes: 3 additions & 3 deletions src/Network/NWBrowser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,18 +131,18 @@ public NWParameters Parameters
[DllImport (Constants.NetworkLibrary)]
unsafe static extern void nw_browser_set_browse_results_changed_handler (OS_nw_browser browser, BlockLiteral* handler);

delegate void nw_browser_browse_results_changed_handler_t (IntPtr block, IntPtr oldResult, IntPtr newResult, bool completed);
delegate void nw_browser_browse_results_changed_handler_t (IntPtr block, IntPtr oldResult, IntPtr newResult, byte completed);
static nw_browser_browse_results_changed_handler_t static_ChangesHandler = TrampolineChangesHandler;

[MonoPInvokeCallback (typeof (nw_browser_browse_results_changed_handler_t))]
static void TrampolineChangesHandler (IntPtr block, IntPtr oldResult, IntPtr newResult, bool completed)
static void TrampolineChangesHandler (IntPtr block, IntPtr oldResult, IntPtr newResult, byte completed)
{
var del = BlockLiteral.GetTarget<NWBrowserChangesDelegate> (block);
if (del is not null) {
// we do the cleanup of the objs in the internal handlers
NWBrowseResult? nwOldResult = (oldResult == IntPtr.Zero) ? null : new NWBrowseResult (oldResult, owns: false);
NWBrowseResult? nwNewResult = (newResult == IntPtr.Zero) ? null : new NWBrowseResult (newResult, owns: false);
del (nwOldResult, nwNewResult, completed);
del (nwOldResult, nwNewResult, completed != 0);
}
}

Expand Down
20 changes: 10 additions & 10 deletions src/Network/NWConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,15 @@ public unsafe void SetStateChangeHandler (Action<NWConnectionState, NWError?> st
}
}

delegate void nw_connection_boolean_event_handler_t (IntPtr block, [MarshalAs (UnmanagedType.U1)] bool value);
delegate void nw_connection_boolean_event_handler_t (IntPtr block, byte value);
static nw_connection_boolean_event_handler_t static_BooleanChangeHandler = TrampolineBooleanChangeHandler;

[MonoPInvokeCallback (typeof (nw_connection_boolean_event_handler_t))]
static void TrampolineBooleanChangeHandler (IntPtr block, bool value)
static void TrampolineBooleanChangeHandler (IntPtr block, byte value)
{
var del = BlockLiteral.GetTarget<Action<bool>> (block);
if (del is not null)
del (value);
del (value != 0);
}

[DllImport (Constants.NetworkLibrary)]
Expand Down Expand Up @@ -242,15 +242,15 @@ public void SetQueue (DispatchQueue queue)
delegate void nw_connection_receive_completion_t (IntPtr block,
IntPtr dispatchData,
IntPtr contentContext,
[MarshalAs (UnmanagedType.U1)] bool isComplete,
byte isComplete,
IntPtr error);

static nw_connection_receive_completion_t static_ReceiveCompletion = TrampolineReceiveCompletion;
static nw_connection_receive_completion_t static_ReceiveCompletionDispatchData = TrampolineReceiveCompletionData;
static nw_connection_receive_completion_t static_ReceiveCompletionDispatchReadnOnlyData = TrampolineReceiveCompletionReadOnlyData;

[MonoPInvokeCallback (typeof (nw_connection_receive_completion_t))]
static void TrampolineReceiveCompletion (IntPtr block, IntPtr dispatchDataPtr, IntPtr contentContext, bool isComplete, IntPtr error)
static void TrampolineReceiveCompletion (IntPtr block, IntPtr dispatchDataPtr, IntPtr contentContext, byte isComplete, IntPtr error)
{
var del = BlockLiteral.GetTarget<NWConnectionReceiveCompletion> (block);
if (del is not null) {
Expand All @@ -266,7 +266,7 @@ static void TrampolineReceiveCompletion (IntPtr block, IntPtr dispatchDataPtr, I
del (bufferAddress,
bufferSize,
contentContext == IntPtr.Zero ? null : new NWContentContext (contentContext, owns: false),
isComplete,
isComplete != 0,
error == IntPtr.Zero ? null : new NWError (error, owns: false));

if (dispatchData is not null) {
Expand All @@ -277,7 +277,7 @@ static void TrampolineReceiveCompletion (IntPtr block, IntPtr dispatchDataPtr, I
}

[MonoPInvokeCallback (typeof (nw_connection_receive_completion_t))]
static void TrampolineReceiveCompletionData (IntPtr block, IntPtr dispatchDataPtr, IntPtr contentContext, bool isComplete, IntPtr error)
static void TrampolineReceiveCompletionData (IntPtr block, IntPtr dispatchDataPtr, IntPtr contentContext, byte isComplete, IntPtr error)
{
var del = BlockLiteral.GetTarget<NWConnectionReceiveDispatchDataCompletion> (block);
if (del is not null) {
Expand All @@ -289,7 +289,7 @@ static void TrampolineReceiveCompletionData (IntPtr block, IntPtr dispatchDataPt

del (dispatchData,
contentContext == IntPtr.Zero ? null : new NWContentContext (contentContext, owns: false),
isComplete,
isComplete != 0,
error == IntPtr.Zero ? null : new NWError (error, owns: false));

if (dispatchData is not null)
Expand All @@ -298,7 +298,7 @@ static void TrampolineReceiveCompletionData (IntPtr block, IntPtr dispatchDataPt
}

[MonoPInvokeCallback (typeof (nw_connection_receive_completion_t))]
static void TrampolineReceiveCompletionReadOnlyData (IntPtr block, IntPtr dispatchDataPtr, IntPtr contentContext, bool isComplete, IntPtr error)
static void TrampolineReceiveCompletionReadOnlyData (IntPtr block, IntPtr dispatchDataPtr, IntPtr contentContext, byte isComplete, IntPtr error)
{
var del = BlockLiteral.GetTarget<NWConnectionReceiveReadOnlySpanCompletion> (block);
if (del is not null) {
Expand All @@ -307,7 +307,7 @@ static void TrampolineReceiveCompletionReadOnlyData (IntPtr block, IntPtr dispat
var spanData = new ReadOnlySpan<byte> (dispatchData?.ToArray () ?? Array.Empty<byte> ());
del (spanData,
contentContext == IntPtr.Zero ? null : new NWContentContext (contentContext, owns: false),
isComplete,
isComplete != 0,
error == IntPtr.Zero ? null : new NWError (error, owns: false));

if (dispatchData is not null) {
Expand Down
6 changes: 3 additions & 3 deletions src/Network/NWConnectionGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,17 +227,17 @@ public void Send (DispatchData? content, NWEndpoint? endpoint, NWContentContext
[DllImport (Constants.NetworkLibrary)]
unsafe static extern void nw_connection_group_set_receive_handler (OS_nw_connection_group group, uint maximum_message_size, [MarshalAs (UnmanagedType.I1)] bool reject_oversized_messages, BlockLiteral* handler);

delegate void nw_connection_group_receive_handler_t (IntPtr block, IntPtr content, IntPtr context, bool isCompleted);
delegate void nw_connection_group_receive_handler_t (IntPtr block, IntPtr content, IntPtr context, byte isCompleted);
static nw_connection_group_receive_handler_t static_ReceiveHandler = TrampolineReceiveHandler;

[MonoPInvokeCallback (typeof (nw_connection_group_receive_handler_t))]
static void TrampolineReceiveHandler (IntPtr block, IntPtr content, IntPtr context, bool isCompleted)
static void TrampolineReceiveHandler (IntPtr block, IntPtr content, IntPtr context, byte isCompleted)
{
var del = BlockLiteral.GetTarget<NWConnectionGroupReceiveDelegate> (block);
if (del is not null) {
using var nsContent = new DispatchData (content, owns: false);
using var nsContext = new NWContentContext (context, owns: false);
del (nsContent, nsContext, isCompleted);
del (nsContent, nsContext, isCompleted != 0);
}
}

Expand Down
10 changes: 6 additions & 4 deletions src/Network/NWEthernetChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,18 +150,20 @@ public void Send (ReadOnlySpan<byte> content, ushort vlanTag, string remoteAddre
[DllImport (Constants.NetworkLibrary)]
unsafe static extern void nw_ethernet_channel_set_receive_handler (OS_nw_ethernet_channel ethernet_channel, /* [NullAllowed] */ BlockLiteral *handler);

delegate void nw_ethernet_channel_receive_handler_t (IntPtr block, OS_dispatch_data content, ushort vlan_tag, byte[] local_address, byte[] remote_address);
delegate void nw_ethernet_channel_receive_handler_t (IntPtr block, OS_dispatch_data content, ushort vlan_tag, IntPtr local_address, IntPtr remote_address);
static nw_ethernet_channel_receive_handler_t static_ReceiveHandler = TrampolineReceiveHandler;

[MonoPInvokeCallback (typeof (nw_ethernet_channel_receive_handler_t))]
static void TrampolineReceiveHandler (IntPtr block, OS_dispatch_data content, ushort vlanTag, byte[] localAddress, byte[] remoteAddress)
static void TrampolineReceiveHandler (IntPtr block, OS_dispatch_data content, ushort vlanTag, IntPtr localAddressArray, IntPtr remoteAddressArray)
{
// localAddress and remoteAddress are defined as:
// typedef unsigned char nw_ethernet_address_t[6];
var del = BlockLiteral.GetTarget<NWEthernetChannelReceiveDelegate> (block);
if (del is not null) {

var dispatchData = (content == IntPtr.Zero) ? null : new DispatchData (content, owns: false);
var local = (localAddress is null) ? null : Encoding.UTF8.GetString (localAddress);
var remote = (remoteAddress is null) ? null : Encoding.UTF8.GetString (remoteAddress);
var local = Marshal.PtrToStringAuto (localAddressArray, 6);
var remote = Marshal.PtrToStringAuto (remoteAddressArray, 6);

del (dispatchData, vlanTag, local, remote);
}
Expand Down
18 changes: 9 additions & 9 deletions src/Network/NWFramer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,17 +140,17 @@ public Action<NWFramer> StopHandler {
[DllImport (Constants.NetworkLibrary)]
unsafe static extern void nw_framer_set_output_handler (OS_nw_framer framer, void* output_handler);

delegate void nw_framer_set_output_handler_t (IntPtr block, OS_nw_framer framer, OS_nw_protocol_metadata message, nuint message_length, bool is_complete);
delegate void nw_framer_set_output_handler_t (IntPtr block, OS_nw_framer framer, OS_nw_protocol_metadata message, nuint message_length, byte is_complete);
static nw_framer_set_output_handler_t static_OutputHandler = TrampolineOutputHandler;

[MonoPInvokeCallback (typeof (nw_framer_set_output_handler_t))]
static void TrampolineOutputHandler (IntPtr block, OS_nw_framer framer, OS_nw_protocol_metadata message, nuint message_length, bool is_complete)
static void TrampolineOutputHandler (IntPtr block, OS_nw_framer framer, OS_nw_protocol_metadata message, nuint message_length, byte is_complete)
{
var del = BlockLiteral.GetTarget<Action<NWFramer, NWProtocolMetadata, nuint, bool>> (block);
if (del is not null) {
var nwFramer = new NWFramer (framer, owns: true);
var nwProtocolMetadata = new NWFramerMessage (message, owns: true);
del (nwFramer, nwProtocolMetadata, message_length, is_complete);
del (nwFramer, nwProtocolMetadata, message_length, is_complete != 0);
}
}

Expand Down Expand Up @@ -331,18 +331,18 @@ public void ScheduleAsync (Action handler)
[return: MarshalAs (UnmanagedType.I1)]
static extern unsafe bool nw_framer_parse_output (OS_nw_framer framer, nuint minimum_incomplete_length, nuint maximum_length, byte* temp_buffer, BlockLiteral* parse);

delegate void nw_framer_parse_output_t (IntPtr block, IntPtr buffer, nuint buffer_length, bool is_complete);
delegate void nw_framer_parse_output_t (IntPtr block, IntPtr buffer, nuint buffer_length, byte is_complete);
static nw_framer_parse_output_t static_ParseOutputHandler = TrampolineParseOutputHandler;

[MonoPInvokeCallback (typeof (nw_framer_parse_output_t))]
static void TrampolineParseOutputHandler (IntPtr block, IntPtr buffer, nuint buffer_length, bool is_complete)
static void TrampolineParseOutputHandler (IntPtr block, IntPtr buffer, nuint buffer_length, byte is_complete)
{
var del = BlockLiteral.GetTarget<Action<Memory<byte>, bool>> (block);
if (del is not null) {
var bBuffer = new byte [buffer_length];
Marshal.Copy (buffer, bBuffer, 0, (int) buffer_length);
var mValue = new Memory<byte> (bBuffer);
del (mValue, is_complete);
del (mValue, is_complete != 0);
}
}

Expand All @@ -363,18 +363,18 @@ public bool ParseOutput (nuint minimumIncompleteLength, nuint maximumLength, Mem
[return: MarshalAs (UnmanagedType.I1)]
static extern unsafe bool nw_framer_parse_input (OS_nw_framer framer, nuint minimum_incomplete_length, nuint maximum_length, byte* temp_buffer, BlockLiteral* parse);

delegate nuint nw_framer_parse_input_t (IntPtr block, IntPtr buffer, nuint buffer_length, bool is_complete);
delegate nuint nw_framer_parse_input_t (IntPtr block, IntPtr buffer, nuint buffer_length, byte is_complete);
static nw_framer_parse_input_t static_ParseInputHandler = TrampolineParseInputHandler;

[MonoPInvokeCallback (typeof (nw_framer_parse_input_t))]
static nuint TrampolineParseInputHandler (IntPtr block, IntPtr buffer, nuint buffer_length, bool is_complete)
static nuint TrampolineParseInputHandler (IntPtr block, IntPtr buffer, nuint buffer_length, byte is_complete)
{
var del = BlockLiteral.GetTarget<NWFramerParseCompletionDelegate> (block);
if (del is not null) {
var bBuffer = new byte [buffer_length];
Marshal.Copy (buffer, bBuffer, 0, (int) buffer_length);
var mValue = new Memory<byte> (bBuffer);
return del (mValue, is_complete);
return del (mValue, is_complete != 0);
}
return 0;
}
Expand Down
8 changes: 4 additions & 4 deletions src/Network/NWFramerMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,19 @@ public void SetData (string key, byte [] value)
[DllImport (Constants.NetworkLibrary)]
[return: MarshalAs (UnmanagedType.I1)]
unsafe static extern bool nw_framer_message_access_value (OS_nw_protocol_metadata message, IntPtr key, BlockLiteral* access_value);
delegate bool nw_framer_message_access_value_t (IntPtr block, IntPtr data);
delegate byte nw_framer_message_access_value_t (IntPtr block, IntPtr data);
static nw_framer_message_access_value_t static_AccessValueHandler = TrampolineAccessValueHandler;


[MonoPInvokeCallback (typeof (nw_framer_message_access_value_t))]
static bool TrampolineAccessValueHandler (IntPtr block, IntPtr data)
static byte TrampolineAccessValueHandler (IntPtr block, IntPtr data)
{
// get and call, this is internal and we are trying to do all the magic in the call
var del = BlockLiteral.GetTarget<Func<IntPtr, bool>> (block);
if (del is not null) {
return del (data);
return del (data) ? (byte) 1 : (byte) 0;
}
return false;
return 0;
}

[BindingImpl (BindingImplOptions.Optimizable)]
Expand Down
Loading

5 comments on commit 967358c

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

Please sign in to comment.