private static void ValidateSetMessageSendPendingExceptionImpl(MessageSendFunction msgSend) { if (!LibObjC.SupportedOnPlatform(msgSend)) { return; } IntPtr func = msgSend switch { MessageSendFunction.MsgSend => (IntPtr)(delegate * unmanaged <IntPtr, IntPtr, IntPtr>) & MsgSend, MessageSendFunction.MsgSendFpret => (IntPtr)(delegate * unmanaged <IntPtr, IntPtr, IntPtr>) & MsgSendFpret, MessageSendFunction.MsgSendStret => (IntPtr)(delegate * unmanaged <IntPtr *, IntPtr, IntPtr, void>) & MsgSendStret, MessageSendFunction.MsgSendSuper => (IntPtr)(delegate * unmanaged <IntPtr, IntPtr, IntPtr>) & MsgSendSuper, MessageSendFunction.MsgSendSuperStret => (IntPtr)(delegate * unmanaged <IntPtr *, IntPtr, IntPtr, void>) & MsgSendSuperStret, _ => throw new Exception($"Unknown {nameof(MessageSendFunction)}"), }; // Override message send function // // We are using the overriding mechanism to enable validating in the Libraries test suite. // Technically any Objective-C code that is entered via msgSend could call the managed SetMessageSendPendingException() // and it would be thrown when returning from the P/Invoke. This approach avoids us having to // create a pure Objective-C library for testing this behavior. ObjectiveCMarshal.SetMessageSendCallback(msgSend, func); // Call message send function through P/Invoke IntPtr inst = IntPtr.Zero; IntPtr sel = IntPtr.Zero; Exception ex = Assert.Throws <PendingException>(() => LibObjC.CallPInvoke(msgSend, inst, sel)); Assert.Equal(msgSend.ToString(), ex.Message); }
public static IntPtr CallPInvoke(MessageSendFunction msgSend, IntPtr inst, IntPtr sel) { switch (msgSend) { case MessageSendFunction.MsgSend: return(LibObjC.objc_msgSend(inst, sel)); case MessageSendFunction.MsgSendFpret: return(LibObjC.objc_msgSend_fpret(inst, sel)); case MessageSendFunction.MsgSendStret: { IntPtr ret; LibObjC.objc_msgSend_stret(out ret, inst, sel); return(ret); } case MessageSendFunction.MsgSendSuper: return(LibObjC.objc_msgSendSuper(inst, sel)); case MessageSendFunction.MsgSendSuperStret: { IntPtr ret; LibObjC.objc_msgSendSuper_stret(out ret, inst, sel); return(ret); } default: throw new ArgumentException($"Unknown {nameof(MessageSendFunction)}: {msgSend}"); } }
public void ValidateSetMessageSendPendingException(MessageSendFunction func) { // Pass functions to override as a string for remote execution RemoteExecutor.Invoke((string funcToOverrideAsStr) => { MessageSendFunction msgSend = Enum.Parse <MessageSendFunction>(funcToOverrideAsStr); Assert.True(Enum.IsDefined <MessageSendFunction>(msgSend)); ValidateSetMessageSendPendingExceptionImpl(msgSend); }, func.ToString()).Dispose(); }
public static bool SupportedOnPlatform(MessageSendFunction msgSend) { // The objc_msgSend_fpret, objc_msgSend_stret, and objc_msgSendSuper_stret exports // are not present on the ARM64 platform. if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64 && (msgSend == MessageSendFunction.MsgSendFpret || msgSend == MessageSendFunction.MsgSendStret || msgSend == MessageSendFunction.MsgSendSuperStret)) { return(false); } return(true); }
public void ValidateSetMessageSendPendingException(MessageSendFunction func) { // Pass functions to override as a string for remote execution RemoteExecutor.Invoke((string funcToOverrideAsStr) => { MessageSendFunction msgSend = Enum.Parse <MessageSendFunction>(funcToOverrideAsStr); Assert.True(Enum.IsDefined <MessageSendFunction>(msgSend)); ValidateSetMessageSendPendingExceptionImpl(msgSend); // TODO: Remove once https://github.com/dotnet/arcade/issues/5865 is resolved // RemoteExecutor currently only checks the expected exit code if the invoked function returns an int. // Check the exit code to ensure the test will fail if there was a crash that could not be caught by the executor. return(RemoteExecutor.SuccessExitCode); }, func.ToString()).Dispose(); }
private static extern bool TrySetGlobalMessageSendCallback( MessageSendFunction msgSendFunction, IntPtr func);
/// <summary> /// Set a function pointer override for an Objective-C runtime message passing export. /// </summary> /// <param name="msgSendFunction">The export to override.</param> /// <param name="func">The function override.</param> /// <exception cref="InvalidOperationException">Thrown if the msgSend function has already been overridden.</exception> /// <remarks> /// Providing an override can enable support for Objective-C variadic argument support. /// </remarks> public static void SetMessageSendCallback(MessageSendFunction msgSendFunction, IntPtr func) => throw new PlatformNotSupportedException();
private static bool TrySetGlobalMessageSendCallback( MessageSendFunction msgSendFunction, IntPtr func) => throw new NotImplementedException();
private static IntPtr ReturnPtr(MessageSendFunction msgSendFunc) { s_callbackInvoked = true; return(new IntPtr(s_count + (int)msgSendFunc)); }