-
Notifications
You must be signed in to change notification settings - Fork 4.6k
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
Reconcile blittable and unmanaged concepts #59824
Comments
Today, the blittable concept in the runtime is not equivalent to the unmanaged concept in the C# language. Blittable types are a subset of unmanaged types, mainly due to back-compat issues around .NET's initial Windows-focused nature. All primitives except For the source-generated marshalling system, we can make the choice to break these back-compat defaults and instead treat Given the following struct type: struct MyStruct
{
public char c;
public bool f;
public byte b;
} In the current built-in system, this maps to the following native struct: struct MyStruct // size 12, alignment 4
{
char c; // Offset 0
BOOL b; // Offset 4
byte b; // Offset 8
}; whereas with an "unmanaged == blittable" system: struct MyStruct // size 4, alignment 2
{
char16_t c; // Offset 0
bool b; // Offset 2
byte b; // Offset 3
}; Because the differences between the two systems would be quite drastic, we would need to determine a good mechanism to warn users about structures that may have large differences between the old and new systems. Additionally, we would need to consider types that are defined in other assemblies (possibly in other NuGet packages) that may not have their full surface area exposed publicly (so it might not be possible to detect that it has Also, as part of this work, we should make sure to keep the defaults for |
After thinking about this more and having some more conversations, here's a few implementation considerations that we need to think about if we go the reconciliation route (unmanaged == blittable route). We need to consider how this new system interacts with the existing Marshal APIs like SizeOf, StructureToPtr, PtrToStructure, etc. The new behavior would not align with the old behavior, so we'd need to consider how we ensure that users do not shoot themselves in the foot. Analyzers would be helpful here, but detecting when a struct is used in the new system and with these APIs might be a difficult problem. Thankfully, with the existence of the new As the GeneratedDllImport design uses a regular DllImport under the hood, we need some mechanism (that's public so DllImportGenerator can use it) to indicate to the built-in system to treat unmanaged == blittable. Below I've included a few options:
This solution works for DllImportGenerator, but it prevents other developers from reusing the core of our marshalling logic to build their own generator based on function pointers. For example, being able to write a source-generator model to provide a "DllImport-like" surface for OpenGL/Vulkan APIs or other APIs that need #1906 by using function pointers to call into native instead of
This mechanism has its own pros and cons:
|
You do not even need to use BTW: It is not unusual to see bugs where people use
I think it is important that we have something that works well for function pointers. One more option to consider: Global assembly setting that says "this assembly does not depend on built-in interop support". It can be a new bit on |
I like the idea of making something available assembly-wide to say "don't use the old marshalling system at all". That would be something that the Mono team could build off with their componentized runtime work. If they were to move the built-in marshalling subsystem to a component, they could exclude it if all assemblies either opt-in to using the new system or don't use DllImports/interop marshalling at all (which could be determined at build time). |
This would probably be a good scenario for extending the |
Closing since #60639 now provides a reconciliation mechanism. |
C# has the concept of an
unmanaged
constraint, but that does not map to blittability for interop in the runtime. We should investigate reconciling the two.See #59658 (comment)
cc @AaronRobinsonMSFT @jaredpar @jkoritzinsky @lambdageek
The text was updated successfully, but these errors were encountered: