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 using DllImportAttribute.
This approach complements UnmanagedCallersOnlyAttribute and aligns with the reuse of the CallConv* types under the System.Runtime.CompilerServices namespace.
Proposed API
If the user specifies the CallingConvention.Winapi (the default) on the DllImportAttribute the following attribute will be queried.
namespace System.Runtime.InteropServices
{
+ /// <summary>
+ /// Provides an equivalent to <see cref="UnmanagedCallersOnlyAttribute"/> for native
+ /// functions declared in .NET.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Method)]
+ public class UnmanagedCalleeAttribute : Attribute
+ {
+ public UnmanagedCalleeAttribute() { }
+
+ /// <summary>
+ /// Types indicating calling conventions for the unmanaged callee.
+ /// </summary>
+ /// <remarks>
+ /// If <c>null</c>, the semantics are identical to <c>CallingConvention.Winapi</c>.
+ /// </remarks>
+ public Type[]? CallConvs;
+ }
}
Usage Examples
P/Invoke
Using the defaults, all 3 of the following declarations are the same.
[DllImport("nativelib")]
static extern int Func(IntPtr a, nint val);
[DllImport("nativelib", CallingConvention = CallingConvention.Winapi)]
static extern int Func(IntPtr a, nint val);
[UnmanagedCallee]
[DllImport("nativelib")]
static extern int Func(IntPtr a, nint val);
Some calling conventions can be declared in multiple ways.
[DllImport("nativelib", CallingConvention = CallingConvention.Cdecl)]
static extern int Func(IntPtr a, nint val);
[UnmanagedCallee(CallConvs = new[] { typeof(CallConvCdecl) })]
[DllImport("nativelib")]
static extern int Func(IntPtr a, nint val);
[UnmanagedCallee(CallConvs = new[] { typeof(CallConvCdecl) })]
[DllImport("nativelib", CallingConvention = CallingConvention.Winapi)]
static extern int Func(IntPtr a, nint val);
Future calling conventions would be enabled without updating the CallingConvention enum. Examples in C# and VB.NET.
[UnmanagedCallee(CallConvs = new[] { typeof(CallConvVectorCall) })]
[DllImport("nativelib")]
static extern int Func(IntPtr a, nint val);
<UnmanagedCallee(CallConvs := New Type() { GetType(CallConvVectorCall) })>
<DllImport("nativelib")>
Public Shared Function Func(a As IntPtr, val As IntPtr) As Integer
End Function
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.
[ComVisible(true)]
[Guid("C509A1C1-A6C9-4229-89CE-10B53CF8271B")]
interface IFoo
{
int Call(ref SomeType valuetype);
}
[ComVisible(true)]
[Guid("C509A1C1-A6C9-4229-89CE-10B53CF8271B")]
[UnmanagedCallee]
interface IFoo
{
int Call(ref SomeType valuetype);
}
[ComVisible(true)]
[Guid("C509A1C1-A6C9-4229-89CE-10B53CF8271B")]
[UnmanagedCallee(CallConvs = new[] { typeof(CallConvStdCall), typeof(CallConvMemberInstance) })]
interface IFoo
{
int Call(ref SomeType valuetype);
}
Alternative Designs
Provide an enum to trigger off for reading the new attribute.
namespace System.Runtime.InteropServices
{
public enum CallingConvention
{
+ /// <summary>
+ /// Instructs the runtime to consult the <see cref="UnmanagedCalleeAttribute"/>.
+ /// </summary>
+ UnmanagedCallee = 7
}
}
Alternative name proposed could be CallingConvention.UnmanagedCallConv.
Background and Motivation
The
UnmanagedCallersOnlyAttributeprovides 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
UnmanagedCallersOnlyAttributeand aligns with the reuse of theCallConv*types under theSystem.Runtime.CompilerServicesnamespace.Proposed API
If the user specifies the
CallingConvention.Winapi(the default) on theDllImportAttributethe following attribute will be queried.namespace System.Runtime.InteropServices { + /// <summary> + /// Provides an equivalent to <see cref="UnmanagedCallersOnlyAttribute"/> for native + /// functions declared in .NET. + /// </summary> + [AttributeUsage(AttributeTargets.Method)] + public class UnmanagedCalleeAttribute : Attribute + { + public UnmanagedCalleeAttribute() { } + + /// <summary> + /// Types indicating calling conventions for the unmanaged callee. + /// </summary> + /// <remarks> + /// If <c>null</c>, the semantics are identical to <c>CallingConvention.Winapi</c>. + /// </remarks> + public Type[]? CallConvs; + } }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
CallingConventionenum. 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.
namespace System.Runtime.InteropServices { public enum CallingConvention { + /// <summary> + /// Instructs the runtime to consult the <see cref="UnmanagedCalleeAttribute"/>. + /// </summary> + UnmanagedCallee = 7 } }Alternative name proposed could be
CallingConvention.UnmanagedCallConv.