-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Extensible Calling Conventions for native callee functions #51156
Comments
It took me a second to put this together😄 If I understood right, for future calling conventions, we basically annotate as What is the behavior if the attribute doesn't exist or contains invalid types? |
Yep. This is handling the case where someone wants to consume a native function. We have it already for C# function pointers so we have
Yes. Now we can enable all existing interop mechanisms to consume the
My preference would be a hard fail. The attribute is the contract and the
Great question. I would say on the closest enclosing type. From the runtime data structure view it would be what is on the associated
You're the first. Will add. |
A alternative design would be allow this attribute with the default calling convention, ie:
It looks better, but it is more expensive at runtime because we have to lookup an extra attribute most of the time. I am not sure which one I like better. FWIW, we have introduced an extra attribute lookup for SuppressGCTransitionAttribute recently and it has not showed up on the radar, so adding one more would be probably fine.
I think we should keep this simple and only support this on DllImport methods. We can always extend it later if needed. None of the existing CallConv constructs (function pointers, UnmanagedCallersOnlyAttribute) have a type default like this. |
Agreed. I had considered this approach because of the potential tooling impact of adding a new enum value. Would you then get rid of the new enum entirely?
That is true, but this one will likely have data content as opposed to
That is reasonable. |
Yep. |
Another aspect of the default proposal is that regardless of the user setting I'm a little leery of that approach because I would prefer this sort of thing to be explicit and not a magic contract. However, a rebuttal to that is it follows our desire to make the default declaration the canonical approach and move away from mechanisms that expose .NET's legacy x86 focus – see C#'s function pointer design. I am also moving this to .NET 6 since I would like to fold support here into the DllImport source generator and be able to avoid the |
In IL there's a way to disambiguate between Winapi and no setting, but Roslyn makes the default Winapi, so we'd have to check for the attribute whenever Winapi is set. |
Really? How do we do that in IL? |
In IL, in the |
Gotcha. I completely misunderstood your statement but see what you are saying. You mean actually writing in IL it can be elided and an IL parser recognizes that - sure. The issue here is from a metadata perspective - which is where we are in the runtime - there is no difference so we can't make that determination, unless there is something I am missing. |
When we're in the runtime, we can distinguish between someone specifying Since we can't disambiguate when developers are using C#, we still need to check for the attribute when they use Winapi. |
Sigh. Apologies. I genuinely thought Winapi was 0 in this case. Confused between all our callconv flags in the runtime. Understand your point now. |
namespace System.Runtime.InteropServices
{
/// <summary>
/// Provides an equivalent to <see cref="UnmanagedCallersOnlyAttribute"/> for native
/// functions declared in .NET.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class UnmanagedCallConvAttribute : Attribute
{
public UnmanagedCallConvAttribute() { }
/// <summary>
/// Types indicating calling conventions for the unmanaged target.
/// </summary>
/// <remarks>
/// If <c>null</c>, the semantics are identical to <c>CallingConvention.Winapi</c>.
/// </remarks>
public Type[]? CallConvs;
}
} |
Addressed with #52869 |
Background and Motivation
The
UnmanagedCallersOnlyAttribute
provides an extensible mechanism to define native calling conventions on a .NET method. This enables users to author functions that are callable in a native environment. A symmetrical need arises for functions that are defined in native code but declared to be called in a .NET environment. These native function declarations are done usingDllImportAttribute
.This approach complements
UnmanagedCallersOnlyAttribute
and aligns with the reuse of theCallConv*
types under theSystem.Runtime.CompilerServices
namespace.Proposed API
If the user specifies the
CallingConvention.Winapi
(the default) on theDllImportAttribute
the following attribute will be queried.Usage Examples
P/Invoke
Using the defaults, all 3 of the following declarations are the same.
Some calling conventions can be declared in multiple ways.
Future calling conventions would be enabled without updating the
CallingConvention
enum. Examples in C# and VB.NET.This proposal provides an alternative mechanism to support Native Varargs in #48796.
COM style interface - Not proposed but example of how the attribute could evolve.
To enable this scenario the attribute would be updated with the following:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
Using the defaults, all 3 of the following declarations are the same on Windows.
Alternative Designs
Provide an enum to trigger off for reading the new attribute.
Alternative name proposed could be
CallingConvention.UnmanagedCallConv
.The text was updated successfully, but these errors were encountered: