-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Implement System.Runtime.CompilerServices.DisabledRuntimeMarshallingAttribute on CoreCLR-family of runtimes/type systems #63320
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
Changes from 1 commit
95c08cf
225dea7
7c85f02
132dc67
70f2fab
ae4f309
8681adf
7700998
20094a2
f9f070f
e0ee72e
694f5fb
9ca4274
e84d87d
a4a8c99
a0953a2
118e21c
57c5553
8c7efa3
ce914dc
e72845f
bcfa307
abf48cb
517833f
8eee013
9d58b3f
9bb7a62
887e20a
a8671be
e1d26fc
f928557
754ffaf
149ba9f
82c0086
d759243
4218e1d
54dc419
5ae53f8
41a4474
adb46bc
1b26307
5c70dc2
b8588dc
f2d91ff
f2f773d
46c12bb
4c49207
a660f12
f0c86ec
57c482b
d0e12db
7524223
b62fd52
e3b7686
2ecd865
7b0f9b2
3122f76
0d1f54e
6a08e87
9e0fc41
0896e44
3609c82
74b0f61
f496d66
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| project (DisabledRuntimeMarshallingNative) | ||
| include_directories(${INC_PLATFORM_DIR}) | ||
| set(SOURCES DisabledRuntimeMarshallingNative.cpp ) | ||
|
|
||
| # add the executable | ||
| add_library (DisabledRuntimeMarshallingNative SHARED ${SOURCES}) | ||
| target_link_libraries(DisabledRuntimeMarshallingNative ${LINK_LIBRARIES_ADDITIONAL}) | ||
|
|
||
| # add the install targets | ||
| install (TARGETS DisabledRuntimeMarshallingNative DESTINATION bin) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| // 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.InteropServices; | ||
| using Xunit; | ||
| using static DisabledRuntimeMarshallingNative; | ||
|
|
||
| namespace DisabledRuntimeMarshalling.Common; | ||
|
|
||
| public unsafe class DelegatesFromExternalAssembly | ||
| { | ||
| [Fact] | ||
| public static void StructWithDefaultNonBlittableFields_DoesNotMarshal() | ||
| { | ||
| short s = 42; | ||
| bool b = true; | ||
|
|
||
| var callback = Marshal.GetDelegateForFunctionPointer<CheckStructWithShortAndBoolCallback>((IntPtr)DisabledRuntimeMarshallingNative.GetStructWithShortAndBoolCallback()); | ||
|
|
||
| Assert.True(callback(new StructWithShortAndBool(s, b), s, b)); | ||
| } | ||
|
|
||
| [Fact] | ||
| public static void StructWithDefaultNonBlittableFields_IgnoresMarshalAsInfo() | ||
| { | ||
| short s = 41; | ||
| bool b = true; | ||
|
|
||
| var callback = Marshal.GetDelegateForFunctionPointer<CheckStructWithShortAndBoolWithMarshalAsCallback>((IntPtr)DisabledRuntimeMarshallingNative.GetStructWithShortAndBoolWithMarshalAsCallback()); | ||
|
|
||
| Assert.True(callback(new StructWithShortAndBoolWithMarshalAs(s, b), s, b)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| // 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.InteropServices; | ||
| using Xunit; | ||
| using static DisabledRuntimeMarshallingNative; | ||
|
|
||
| namespace DisabledRuntimeMarshalling.DefaultOnly; | ||
|
|
||
| public class PInvokes | ||
| { | ||
| [Fact] | ||
| public static void StructWithDefaultNonBlittableFields() | ||
| { | ||
| short s = 42; | ||
| bool b = true; | ||
|
|
||
| Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithShortAndBool(new StructWithShortAndBool(s, b), s, b)); | ||
|
|
||
| // We use a the "green check mark" character so that we use both bytes and | ||
| // have a value that can't be accidentally round-tripped. | ||
| char c = '✅'; | ||
| Assert.False(DisabledRuntimeMarshallingNative.CheckStructWithWCharAndShort(new StructWithWCharAndShort(s, c), s, c)); | ||
|
|
||
| } | ||
| [Fact] | ||
| public static void StructWithDefaultNonBlittableFields_MarshalAsInfo() | ||
| { | ||
| short s = 41; | ||
| bool b = true; | ||
|
|
||
| Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithShortAndBool(new StructWithShortAndBoolWithMarshalAs(s, b), s, b)); | ||
|
|
||
| // We use a the "green check mark" character so that we use both bytes and | ||
| // have a value that can't be accidentally round-tripped. | ||
| char c = '✅'; | ||
| Assert.False(DisabledRuntimeMarshallingNative.CheckStructWithWCharAndShort(new StructWithWCharAndShortWithMarshalAs(s, c), s, c)); | ||
|
|
||
| Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithShortAndBoolWithVariantBool(new StructWithShortAndBool(s, b), s, b)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| // 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 Xunit; | ||
| using static DisabledRuntimeMarshallingNative; | ||
|
|
||
| namespace DisabledRuntimeMarshalling.DisabledMarshallingOnly; | ||
|
|
||
| public class PInvokes | ||
| { | ||
|
|
||
| [Fact] | ||
| public static void StructWithDefaultNonBlittableFields_MarshalAsInfo() | ||
| { | ||
| short s = 41; | ||
| bool b = true; | ||
|
|
||
| Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithShortAndBool(new StructWithShortAndBoolWithMarshalAs(s, b), s, b)); | ||
|
|
||
| // We use a the "green check mark" character so that we use both bytes and | ||
| // have a value that can't be accidentally round-tripped. | ||
| char c = '✅'; | ||
| Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithWCharAndShort(new StructWithWCharAndShortWithMarshalAs(s, c), s, c)); | ||
| } | ||
|
|
||
| [Fact] | ||
| public static void Strings_NotSupported() | ||
| { | ||
| Assert.Throws<NotSupportedException>(() => DisabledRuntimeMarshallingNative.CheckStringWithAnsiCharSet("")); | ||
| Assert.Throws<NotSupportedException>(() => DisabledRuntimeMarshallingNative.CheckStringWithUnicodeCharSet("")); | ||
| Assert.Throws<NotSupportedException>(() => DisabledRuntimeMarshallingNative.CheckStructWithStructWithString(new StructWithString(""))); | ||
| Assert.Throws<NotSupportedException>(() => DisabledRuntimeMarshallingNative.GetStringWithUnicodeCharSet()); | ||
| } | ||
|
|
||
| [Fact] | ||
| public static void LayoutClass_NotSupported() | ||
| { | ||
| Assert.Throws<NotSupportedException>(() => DisabledRuntimeMarshallingNative.CheckLayoutClass(new LayoutClass())); | ||
| } | ||
|
|
||
| [Fact] | ||
| public static void NoBooleanNormalization() | ||
| { | ||
| byte byteVal = 42; | ||
| Assert.Equal(byteVal, Unsafe.As<bool, byte>(ref Unsafe.AsRef(DisabledRuntimeMarshallingNative.GetByteAsBool(byteVal)))); | ||
| } | ||
|
|
||
| [Fact] | ||
| public static void StructWithDefaultNonBlittableFields_DoesNotDoMarshalling() | ||
| { | ||
| short s = 42; | ||
| bool b = true; | ||
|
|
||
| Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithShortAndBool(new StructWithShortAndBool(s, b), s, b)); | ||
|
|
||
| // We use a the "green check mark" character so that we use both bytes and | ||
| // have a value that can't be accidentally round-tripped. | ||
| char c = '✅'; | ||
| Assert.True(DisabledRuntimeMarshallingNative.CheckStructWithWCharAndShort(new StructWithWCharAndShort(s, c), s, c)); | ||
|
|
||
| Assert.False(DisabledRuntimeMarshallingNative.CheckStructWithShortAndBoolWithVariantBool_FailureExpected(new StructWithShortAndBool(s, b), s, b)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| #include <xplatform.h> | ||
|
|
||
| struct StructWithShortAndBool | ||
| { | ||
| short s; | ||
| bool b; | ||
| }; | ||
|
|
||
| struct StructWithWCharAndShort | ||
| { | ||
| short s; | ||
| WCHAR c; | ||
| }; | ||
|
|
||
| extern "C" DLL_EXPORT bool STDMETHODCALLTYPE CheckStructWithShortAndBool(StructWithShortAndBool str, short s, bool b) | ||
| { | ||
| return str.s == s && str.b == b; | ||
| } | ||
|
|
||
| extern "C" DLL_EXPORT bool STDMETHODCALLTYPE CheckStructWithWCharAndShort(StructWithWCharAndShort str, short s, WCHAR c) | ||
| { | ||
| return str.s == s && str.c == c; | ||
| } | ||
|
|
||
| using CheckStructWithShortAndBoolCallback = bool (STDMETHODCALLTYPE*)(StructWithShortAndBool, short, bool); | ||
|
|
||
| extern "C" DLL_EXPORT CheckStructWithShortAndBoolCallback STDMETHODCALLTYPE GetStructWithShortAndBoolCallback() | ||
| { | ||
| return &CheckStructWithShortAndBool; | ||
| } | ||
|
|
||
| extern "C" DLL_EXPORT BYTE PassThrough(BYTE b) | ||
| { | ||
| return b; | ||
| } | ||
|
|
||
| extern "C" DLL_EXPORT void Invalid(...) {} | ||
|
|
||
| #ifdef _WIN32 | ||
| extern "C" DLL_EXPORT bool STDMETHODCALLTYPE CheckStructWithShortAndBoolWithVariantBool(StructWithShortAndBool str, short s, VARIANT_BOOL b) | ||
| { | ||
| // Specifically use VARIANT_TRUE here as invalid marshalling (in the "disabled runtime marshalling" case) will incorrectly marshal VARAINT_TRUE | ||
| // but could accidentally marshal VARIANT_FALSE correctly since it is 0, which is the same representation as a zero or sign extension of the C# false value. | ||
| return str.s == s && str.b == (b == VARIANT_TRUE); | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
jkoritzinsky marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| <PropertyGroup> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <Compile Include="Common/*.cs" /> | ||
| <Compile Include="DisabledMarshallingOnly/*.cs" /> | ||
| <Compile Include="RuntimeMarshallingDisabledAttribute.cs" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <ProjectReference Include="Native_DisabledMarshalling/DisabledRuntimeMarshallingNative_DisabledMarshalling.csproj" /> | ||
| <ProjectReference Include="CMakeLists.txt" /> | ||
| </ItemGroup> | ||
| </Project> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
| <PropertyGroup> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <Compile Include="Common/*.cs" /> | ||
| <Compile Include="DefaultOnly/*.cs" /> | ||
| <Compile Include="RuntimeMarshallingDisabledAttribute.cs" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <ProjectReference Include="Native_Default/DisabledRuntimeMarshallingNative_Default.csproj" /> | ||
| <ProjectReference Include="CMakeLists.txt" /> | ||
| </ItemGroup> | ||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
| <PropertyGroup> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <Compile Include="Common/*.cs" /> | ||
| <Compile Include="DisabledMarshallingOnly/*.cs" /> | ||
| <Compile Include="Native_DisabledMarshalling/DisabledRuntimeMarshallingNative.cs" /> | ||
| <Compile Include="RuntimeMarshallingDisabledAttribute.cs" /> | ||
| <ProjectReference Include="CMakeLists.txt" /> | ||
| </ItemGroup> | ||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
jkoritzinsky marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| <PropertyGroup> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <Compile Include="Common/*.cs" /> | ||
| <Compile Include="DisabledMarshallingOnly/*.cs" /> | ||
| <Compile Include="RuntimeMarshallingDisabledAttribute.cs" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <ProjectReference Include="Native_DisabledMarshalling/DisabledRuntimeMarshallingNative_DisabledMarshalling.csproj" /> | ||
| <ProjectReference Include="CMakeLists.txt" /> | ||
| </ItemGroup> | ||
| </Project> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| // 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.InteropServices; | ||
| using Xunit; | ||
|
|
||
| public unsafe class DisabledRuntimeMarshallingNative | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For after this PR: thoughts on pulling out the common parts between this and the one under
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe... Depends on how much would actually be common between the two. |
||
| { | ||
| public struct StructWithShortAndBool | ||
| { | ||
| short s; | ||
| [MarshalAs(UnmanagedType.U1)] | ||
| bool b; | ||
|
|
||
| public StructWithShortAndBool(short s, bool b) | ||
| { | ||
| this.s = s; | ||
| this.b = b; | ||
| } | ||
| } | ||
|
|
||
| public struct StructWithShortAndBoolWithMarshalAs | ||
| { | ||
| short s; | ||
| [MarshalAs(UnmanagedType.U1)] | ||
| bool b; | ||
|
|
||
| public StructWithShortAndBoolWithMarshalAs(short s, bool b) | ||
| { | ||
| this.s = s; | ||
| this.b = b; | ||
| } | ||
| } | ||
|
|
||
| public struct StructWithWCharAndShort | ||
| { | ||
| short s; | ||
| [MarshalAs(UnmanagedType.U2)] | ||
| char c; | ||
|
|
||
| public StructWithWCharAndShort(short s, char c) | ||
| { | ||
| this.s = s; | ||
| this.c = c; | ||
| } | ||
| } | ||
|
|
||
| [StructLayout(LayoutKind.Sequential)] | ||
| public struct StructWithWCharAndShortWithMarshalAs | ||
| { | ||
| short s; | ||
| [MarshalAs(UnmanagedType.U2)] | ||
| char c; | ||
|
|
||
| public StructWithWCharAndShortWithMarshalAs(short s, char c) | ||
| { | ||
| this.s = s; | ||
| this.c = c; | ||
| } | ||
| } | ||
|
|
||
| public struct StructWithString | ||
| { | ||
| string s; | ||
|
|
||
| public StructWithString(string s) | ||
| { | ||
| this.s = s; | ||
| } | ||
| } | ||
|
|
||
| [StructLayout(LayoutKind.Sequential)] | ||
| public class LayoutClass | ||
| {} | ||
|
|
||
| [DllImport(nameof(DisabledRuntimeMarshallingNative))] | ||
| [return:MarshalAs(UnmanagedType.U1)] | ||
| public static extern bool CheckStructWithShortAndBool(StructWithShortAndBool str, short s, bool b); | ||
| [DllImport(nameof(DisabledRuntimeMarshallingNative))] | ||
| [return:MarshalAs(UnmanagedType.U1)] | ||
| public static extern bool CheckStructWithShortAndBool(StructWithShortAndBoolWithMarshalAs str, short s, [MarshalAs(UnmanagedType.Bool)] bool b); | ||
| [DllImport(nameof(DisabledRuntimeMarshallingNative))] | ||
| [return:MarshalAs(UnmanagedType.U1)] | ||
| public static extern bool CheckStructWithWCharAndShort(StructWithWCharAndShort str, short s, char c); | ||
| [DllImport(nameof(DisabledRuntimeMarshallingNative))] | ||
| [return:MarshalAs(UnmanagedType.U1)] | ||
| public static extern bool CheckStructWithWCharAndShort(StructWithWCharAndShortWithMarshalAs str, short s, [MarshalAs(UnmanagedType.U1)] char c); | ||
|
|
||
| [DllImport(nameof(DisabledRuntimeMarshallingNative))] | ||
| public static extern delegate*<StructWithShortAndBool, short, bool, bool> GetStructWithShortAndBoolCallback(); | ||
|
|
||
| [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "GetStructWithShortAndBoolCallback")] | ||
| public static extern delegate*<StructWithShortAndBoolWithMarshalAs, short, bool, bool> GetStructWithShortAndBoolWithMarshalAsCallback(); | ||
|
|
||
| [DllImport(nameof(DisabledRuntimeMarshallingNative), EntryPoint = "PassThrough")] | ||
| [return:MarshalAs(UnmanagedType.U1)] | ||
| public static extern bool GetByteAsBool(byte b); | ||
|
|
||
| [DllImport(nameof(DisabledRuntimeMarshallingNative))] | ||
| [return:MarshalAs(UnmanagedType.U1)] | ||
| public static extern bool CheckStructWithShortAndBoolWithVariantBool(StructWithShortAndBool str, short s, [MarshalAs(UnmanagedType.VariantBool)] bool b); | ||
|
|
||
| public delegate bool CheckStructWithShortAndBoolCallback(StructWithShortAndBool str, short s, bool b); | ||
| public delegate bool CheckStructWithShortAndBoolWithMarshalAsCallback(StructWithShortAndBoolWithMarshalAs str, short s, [MarshalAs(UnmanagedType.Bool)] bool b); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
| <PropertyGroup> | ||
| <OutputType>Library</OutputType> | ||
| <CLRTestKind>SharedLibrary</CLRTestKind> | ||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <Compile Include="DisabledRuntimeMarshallingNative.cs" /> | ||
| </ItemGroup> | ||
| </Project> |
Uh oh!
There was an error while loading. Please reload this page.