-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Swift into .NET using CallConvSwift
and UnmanagedCallersOnly
calling convention
#96059
Comments
Tagging subscribers to this area: @dotnet/interop-contrib Issue DetailsBackground and MotivationFor interop developers calling from Swift into .NET, it is essential to have the ability to access the self register and set the error register. Projection tools will be responsible for ensuring the correct usage of these registers, but at the runtime layer, it should be possible to access them directly. The idea is to leverage the existing API proposal and treat Proposed APIThe proposed example code aims to test delegates and Swift calls into the .NET. The example utilizes the self and context registers as proxies to pass a value. Here's how it works:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Swift;
using Xunit;
public class UnmanagedCallersOnlyTests
{
private const string SwiftLib = "libSwiftUnmanagedCallersOnly.dylib";
[UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvSwift) })]
[DllImport(SwiftLib, EntryPoint = "$s25SwiftUnmanagedCallersOnly26nativeFunctionWithCallbackyyyyXEF")]
public static extern unsafe IntPtr NativeFunctionWithCallback(delegate* unmanaged[Swift]<SwiftSelf, SwiftError*, void> callback, SwiftSelf self, SwiftError* error);
[UnmanagedCallersOnly(CallConvs = new Type[] { typeof(CallConvSwift) })]
private static unsafe void ProxyMethod(SwiftSelf self, SwiftError* error) {
int value = *(int*)self.Value;
Console.WriteLine ("ProxyMethod: {0}", value);
*error = new SwiftError(self.Value);
}
[Fact]
public static unsafe void TestUnmanagedCallersOnly()
{
int expectedValue = 42;
SwiftSelf self = new SwiftSelf((IntPtr)(&expectedValue));
SwiftError error;
NativeFunctionWithCallback(&ProxyMethod, self, &error);
int value = *(int*)error.Value;
Assert.True(value == expectedValue, string.Format("The value retrieved does not match the expected value. Expected: {0}, Actual: {1}", expectedValue, value));
}
} Corresponding Swift code. // Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
public func nativeFunctionWithCallback(_ callback: () -> Void) {
callback()
} The idea is to iterate on this proposal and receive feedback before updating the design document. /cc @dotnet/jit-contrib @dotnet/interop-contrib @lambdageek @rolfbjarne @stephen-hawley @matouskozak @SamMonoRT
|
@kotlarmilos I don't understand this proposal. The entire point of #64215 and the location of the new type means that it can be used with |
Correct. The purpose of this issue is to explore the possibilities of utilizing the existing Swift API for Swift into .NET scenarios. It has not been added to the design document yet, and the intention is to discuss it here before implementing any changes there. |
Do you see any problematic areas to discuss? I think we just need to edit in the design doc to make it clear that both P/Invoke and reverse P/Invoke are in scope. It has been mentioned in #64215 already: "The proposal would be to add built-in support for the Swift ABI via P/Invokes and Reverse P/Invokes". |
Not really, I wasn't sure at first if we would be able to achieve the intended behavior with the reverse P/Invoke. If the sample above is correct, I suggest to close this issue and create a PR that adds more context to the design document and expands the runtime tests. |
Background and Motivation
For interop developers calling from Swift into .NET, it is essential to have the ability to access the self register and set the error register. Projection tools will be responsible for ensuring the correct usage of these registers, but at the runtime layer, it should be possible to access them directly. The idea is to leverage the existing API proposal and treat
UnmanagedCallersOnly
method as a Swift-like method capable of handling self and error registers. This involves reading the self register value in the method prolog and storing it in theSwiftSelf
argument. Additionally, in the method epilog, this involved loading theSwiftError*
value into the error register.Example
The proposed example code aims to test delegates and Swift calls into the .NET. The example utilizes the self and context registers as proxies to pass a value. Here's how it works:
SwiftSelf
instance with an integer valueSwiftSelf
, andSwifterror*
argumentsUnmanagedCallersOnly
C# methodSwiftSelf
andSwiftError*
argumentsSwiftSelf
context pointer is retrieved from the register and stored in the argumentSwiftError*
argument to point to the same valueSwiftError*
is loaded into the error registerCorresponding Swift code.
The idea is to iterate on this proposal and receive feedback before updating the design document.
/cc @dotnet/jit-contrib @dotnet/interop-contrib @lambdageek @rolfbjarne @stephen-hawley @matouskozak @SamMonoRT
The text was updated successfully, but these errors were encountered: