Background and motivation
UnmanagedCallersOnlyAttribute has an EntryPoint property that specifies the method should be available externally under the specified symbolic names. Native AOT and tools like DNNE use this to generate the exports.
This export is unconditonal. If a method in the assembly has this attribute, and the assembly is looked at by the generating tool, the export will be generated and the implementation rooted.
This can be problematic for pregenerated interop code. For example in interop on Apple platforms, the user can specify that their class should be available from native code:
public class MyObject : NSObject
{
[Export("myMethod")]
void MyMethod() {}
}
The interop code will generate a native-callable proxy behind the scenes:
class MyObjectProxy
{
[UnmanagedCallersOnly(EntryPoint = "MyObjectProxy_MyMethod"]
static void MyMethod(IntPtr handle)
{
var obj = (MyObject)Runtime.GetNSObject(handle);
obj.MyMethod();
}
}
The proxy entrypoint is generated with a specified EntryPoint because further native glue code will refer to it.
The proxy entrypoint is however not needed if the MyObject class was never used in the program.
#127575 was asking for a mechanism that would allow specifying a list of EntryPoints to generate. However creating such list requires analyzing the program before native compilation or trimming happens. It would be preferable to connect trimming with the UnmanagedCallersOnly EntryPoint generation logic so that we don't have to effectively run trimming twice.
The subsequent downstream tools can then observe entrypoints that survivied trimming either by inspecting the attribute metadata table in IL in case of IL trimming, or by inspecting the symbols or linker scripts in case of native compilation, or through a custom protocol if inspecting normal compilation outputs is undesirable.
API Proposal
namespace System.Runtime.InteropServices;
public sealed class UnmanagedCallersOnlyAttribute : Attribute
{
public Type? AssociatedType;
}
API Usage
class MyObjectProxy
{
[UnmanagedCallersOnly(EntryPoint = "MyObjectProxy_MyMethod", AssociatedType = typeof(MyObject))]
static void MyMethod(IntPtr handle)
{
var obj = (MyObject)Runtime.GetNSObject(handle);
obj.MyMethod();
}
}
Alternative Designs
Risks
AssociatedType with the rule of "if the an object of this type could exist in the program" may not be sufficiently flexible and additional rules could be needed (for example, what if someone wants this to be generate if some other method was compiled/kept). There are no known uses cases beyond this one type-based rule right now though.
Background and motivation
UnmanagedCallersOnlyAttributehas anEntryPointproperty that specifies the method should be available externally under the specified symbolic names. Native AOT and tools like DNNE use this to generate the exports.This export is unconditonal. If a method in the assembly has this attribute, and the assembly is looked at by the generating tool, the export will be generated and the implementation rooted.
This can be problematic for pregenerated interop code. For example in interop on Apple platforms, the user can specify that their class should be available from native code:
The interop code will generate a native-callable proxy behind the scenes:
The proxy entrypoint is generated with a specified EntryPoint because further native glue code will refer to it.
The proxy entrypoint is however not needed if the
MyObjectclass was never used in the program.#127575 was asking for a mechanism that would allow specifying a list of EntryPoints to generate. However creating such list requires analyzing the program before native compilation or trimming happens. It would be preferable to connect trimming with the UnmanagedCallersOnly EntryPoint generation logic so that we don't have to effectively run trimming twice.
The subsequent downstream tools can then observe entrypoints that survivied trimming either by inspecting the attribute metadata table in IL in case of IL trimming, or by inspecting the symbols or linker scripts in case of native compilation, or through a custom protocol if inspecting normal compilation outputs is undesirable.
API Proposal
API Usage
Alternative Designs
Risks
AssociatedTypewith the rule of "if the an object of this type could exist in the program" may not be sufficiently flexible and additional rules could be needed (for example, what if someone wants this to be generate if some other method was compiled/kept). There are no known uses cases beyond this one type-based rule right now though.