diff --git a/DllImportGenerator/Demo/Demo.csproj b/DllImportGenerator/Demo/Demo.csproj
index fdba3fbbb354..4cee92efcd88 100644
--- a/DllImportGenerator/Demo/Demo.csproj
+++ b/DllImportGenerator/Demo/Demo.csproj
@@ -16,8 +16,4 @@
-
-
-
-
diff --git a/DllImportGenerator/Demo/Program.cs b/DllImportGenerator/Demo/Program.cs
index 06715a76c7c0..f0490390f6ac 100644
--- a/DllImportGenerator/Demo/Program.cs
+++ b/DllImportGenerator/Demo/Program.cs
@@ -15,7 +15,7 @@ partial class NativeExportsNE
public static partial void Sum(int a, ref int b);
}
- unsafe class Program
+ class Program
{
static void Main(string[] args)
{
@@ -31,13 +31,6 @@ static void Main(string[] args)
c = b;
NativeExportsNE.Sum(a, ref c);
Console.WriteLine($"{a} + {b} = {c}");
-
- SafeHandleTests tests = new SafeHandleTests();
-
- tests.ReturnValue_CreatesSafeHandle();
- tests.ByValue_CorrectlyUnwrapsHandle();
- tests.ByRefSameValue_UsesSameHandleInstance();
- tests.ByRefDifferentValue_UsesNewHandleInstance();
}
}
}
diff --git a/DllImportGenerator/DllImportGenerator.IntegrationTests/DllImportGenerator.IntegrationTests.csproj b/DllImportGenerator/DllImportGenerator.IntegrationTests/DllImportGenerator.IntegrationTests.csproj
new file mode 100644
index 000000000000..2932ce632c21
--- /dev/null
+++ b/DllImportGenerator/DllImportGenerator.IntegrationTests/DllImportGenerator.IntegrationTests.csproj
@@ -0,0 +1,29 @@
+
+
+
+ net5.0
+ false
+ Preview
+ true
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
diff --git a/DllImportGenerator/Demo/SafeHandleTests.cs b/DllImportGenerator/DllImportGenerator.IntegrationTests/SafeHandleTests.cs
similarity index 84%
rename from DllImportGenerator/Demo/SafeHandleTests.cs
rename to DllImportGenerator/DllImportGenerator.IntegrationTests/SafeHandleTests.cs
index bb21cfb565ca..fc7171005746 100644
--- a/DllImportGenerator/Demo/SafeHandleTests.cs
+++ b/DllImportGenerator/DllImportGenerator.IntegrationTests/SafeHandleTests.cs
@@ -1,22 +1,22 @@
-
using System.Runtime.InteropServices;
+
using Microsoft.Win32.SafeHandles;
using Xunit;
-namespace Demo
+namespace DllImportGenerator.IntegrationTests
{
partial class NativeExportsNE
{
public class NativeExportsSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
{
- private NativeExportsSafeHandle() : base(true)
- {
- }
+ private NativeExportsSafeHandle() : base(ownsHandle: true)
+ { }
protected override bool ReleaseHandle()
{
- Assert.True(NativeExportsNE.ReleaseHandle(handle));
- return true;
+ bool didRelease = NativeExportsNE.ReleaseHandle(handle);
+ Assert.True(didRelease);
+ return didRelease;
}
}
@@ -57,7 +57,7 @@ public void ByRefSameValue_UsesSameHandleInstance()
{
using NativeExportsNE.NativeExportsSafeHandle handleToDispose = NativeExportsNE.AllocateHandle();
NativeExportsNE.NativeExportsSafeHandle handle = handleToDispose;
- NativeExportsNE.ModifyHandle(ref handle, false);
+ NativeExportsNE.ModifyHandle(ref handle, newHandle: false);
Assert.Same(handleToDispose, handle);
}
@@ -66,7 +66,7 @@ public void ByRefDifferentValue_UsesNewHandleInstance()
{
using NativeExportsNE.NativeExportsSafeHandle handleToDispose = NativeExportsNE.AllocateHandle();
NativeExportsNE.NativeExportsSafeHandle handle = handleToDispose;
- NativeExportsNE.ModifyHandle(ref handle, true);
+ NativeExportsNE.ModifyHandle(ref handle, newHandle: true);
Assert.NotSame(handleToDispose, handle);
handle.Dispose();
}
diff --git a/DllImportGenerator/DllImportGenerator.Test/CodeSnippets.cs b/DllImportGenerator/DllImportGenerator.UnitTests/CodeSnippets.cs
similarity index 99%
rename from DllImportGenerator/DllImportGenerator.Test/CodeSnippets.cs
rename to DllImportGenerator/DllImportGenerator.UnitTests/CodeSnippets.cs
index bb3594897326..06b8156a943c 100644
--- a/DllImportGenerator/DllImportGenerator.Test/CodeSnippets.cs
+++ b/DllImportGenerator/DllImportGenerator.UnitTests/CodeSnippets.cs
@@ -1,6 +1,6 @@
using System.Runtime.InteropServices;
-namespace DllImportGenerator.Test
+namespace DllImportGenerator.UnitTests
{
internal static class CodeSnippets
{
diff --git a/DllImportGenerator/DllImportGenerator.Test/CompileFails.cs b/DllImportGenerator/DllImportGenerator.UnitTests/CompileFails.cs
similarity index 96%
rename from DllImportGenerator/DllImportGenerator.Test/CompileFails.cs
rename to DllImportGenerator/DllImportGenerator.UnitTests/CompileFails.cs
index 3acbdace6ced..bf31ff47d743 100644
--- a/DllImportGenerator/DllImportGenerator.Test/CompileFails.cs
+++ b/DllImportGenerator/DllImportGenerator.UnitTests/CompileFails.cs
@@ -3,7 +3,7 @@
using System.Threading.Tasks;
using Xunit;
-namespace DllImportGenerator.Test
+namespace DllImportGenerator.UnitTests
{
public class CompileFails
{
diff --git a/DllImportGenerator/DllImportGenerator.Test/Compiles.cs b/DllImportGenerator/DllImportGenerator.UnitTests/Compiles.cs
similarity index 99%
rename from DllImportGenerator/DllImportGenerator.Test/Compiles.cs
rename to DllImportGenerator/DllImportGenerator.UnitTests/Compiles.cs
index 3c66f36bbe6d..2275072099fa 100644
--- a/DllImportGenerator/DllImportGenerator.Test/Compiles.cs
+++ b/DllImportGenerator/DllImportGenerator.UnitTests/Compiles.cs
@@ -5,7 +5,7 @@
using System.Threading.Tasks;
using Xunit;
-namespace DllImportGenerator.Test
+namespace DllImportGenerator.UnitTests
{
public class Compiles
{
diff --git a/DllImportGenerator/DllImportGenerator.Test/DllImportGenerator.Test.csproj b/DllImportGenerator/DllImportGenerator.UnitTests/DllImportGenerator.UnitTests.csproj
similarity index 100%
rename from DllImportGenerator/DllImportGenerator.Test/DllImportGenerator.Test.csproj
rename to DllImportGenerator/DllImportGenerator.UnitTests/DllImportGenerator.UnitTests.csproj
diff --git a/DllImportGenerator/DllImportGenerator.Test/ManualTypeMarshallingAnalyzerTests.cs b/DllImportGenerator/DllImportGenerator.UnitTests/ManualTypeMarshallingAnalyzerTests.cs
similarity index 99%
rename from DllImportGenerator/DllImportGenerator.Test/ManualTypeMarshallingAnalyzerTests.cs
rename to DllImportGenerator/DllImportGenerator.UnitTests/ManualTypeMarshallingAnalyzerTests.cs
index e049ce9d4e55..ae3aed147827 100644
--- a/DllImportGenerator/DllImportGenerator.Test/ManualTypeMarshallingAnalyzerTests.cs
+++ b/DllImportGenerator/DllImportGenerator.UnitTests/ManualTypeMarshallingAnalyzerTests.cs
@@ -3,9 +3,9 @@
using Xunit;
using static Microsoft.Interop.ManualTypeMarshallingAnalyzer;
-using VerifyCS = DllImportGenerator.Test.Verifiers.CSharpAnalyzerVerifier;
+using VerifyCS = DllImportGenerator.UnitTests.Verifiers.CSharpAnalyzerVerifier;
-namespace DllImportGenerator.Test
+namespace DllImportGenerator.UnitTests
{
public class ManualTypeMarshallingAnalyzerTests
{
diff --git a/DllImportGenerator/DllImportGenerator.Test/TestUtils.cs b/DllImportGenerator/DllImportGenerator.UnitTests/TestUtils.cs
similarity index 98%
rename from DllImportGenerator/DllImportGenerator.Test/TestUtils.cs
rename to DllImportGenerator/DllImportGenerator.UnitTests/TestUtils.cs
index 49ca8e625f60..e5d79820f991 100644
--- a/DllImportGenerator/DllImportGenerator.Test/TestUtils.cs
+++ b/DllImportGenerator/DllImportGenerator.UnitTests/TestUtils.cs
@@ -9,7 +9,7 @@
using System.Threading.Tasks;
using Xunit;
-namespace DllImportGenerator.Test
+namespace DllImportGenerator.UnitTests
{
internal static class TestUtils
{
diff --git a/DllImportGenerator/DllImportGenerator.Test/Verifiers/CSharpAnalyzerVerifier.cs b/DllImportGenerator/DllImportGenerator.UnitTests/Verifiers/CSharpAnalyzerVerifier.cs
similarity index 98%
rename from DllImportGenerator/DllImportGenerator.Test/Verifiers/CSharpAnalyzerVerifier.cs
rename to DllImportGenerator/DllImportGenerator.UnitTests/Verifiers/CSharpAnalyzerVerifier.cs
index 9ccff97f18b1..b6bd0f531648 100644
--- a/DllImportGenerator/DllImportGenerator.Test/Verifiers/CSharpAnalyzerVerifier.cs
+++ b/DllImportGenerator/DllImportGenerator.UnitTests/Verifiers/CSharpAnalyzerVerifier.cs
@@ -11,7 +11,7 @@
using Microsoft.CodeAnalysis.Testing;
using Microsoft.CodeAnalysis.Testing.Verifiers;
-namespace DllImportGenerator.Test.Verifiers
+namespace DllImportGenerator.UnitTests.Verifiers
{
public static class CSharpAnalyzerVerifier
where TAnalyzer : DiagnosticAnalyzer, new()
diff --git a/DllImportGenerator/DllImportGenerator.Test/Verifiers/CSharpVerifierHelper.cs b/DllImportGenerator/DllImportGenerator.UnitTests/Verifiers/CSharpVerifierHelper.cs
similarity index 97%
rename from DllImportGenerator/DllImportGenerator.Test/Verifiers/CSharpVerifierHelper.cs
rename to DllImportGenerator/DllImportGenerator.UnitTests/Verifiers/CSharpVerifierHelper.cs
index 61c063975270..c51712a3ce0b 100644
--- a/DllImportGenerator/DllImportGenerator.Test/Verifiers/CSharpVerifierHelper.cs
+++ b/DllImportGenerator/DllImportGenerator.UnitTests/Verifiers/CSharpVerifierHelper.cs
@@ -3,7 +3,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-namespace DllImportGenerator.Test.Verifiers
+namespace DllImportGenerator.UnitTests.Verifiers
{
internal static class CSharpVerifierHelper
{
diff --git a/DllImportGenerator/DllImportGenerator.sln b/DllImportGenerator/DllImportGenerator.sln
index b2d908631a36..502dd987bd65 100644
--- a/DllImportGenerator/DllImportGenerator.sln
+++ b/DllImportGenerator/DllImportGenerator.sln
@@ -5,7 +5,7 @@ VisualStudioVersion = 16.0.30204.135
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DllImportGenerator", "DllImportGenerator\DllImportGenerator.csproj", "{0E14E01F-A582-4D22-8737-BF9DE5270435}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DllImportGenerator.Test", "DllImportGenerator.Test\DllImportGenerator.Test.csproj", "{B8CA13C4-F41B-4ABD-A9F3-63A02C53B96E}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DllImportGenerator.UnitTests", "DllImportGenerator.UnitTests\DllImportGenerator.UnitTests.csproj", "{B8CA13C4-F41B-4ABD-A9F3-63A02C53B96E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Demo", "Demo\Demo.csproj", "{E478EE77-E072-4A42-B453-EBFDA7728717}"
EndProject
@@ -13,7 +13,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ancillary.Interop", "Ancill
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestAssets", "TestAssets", "{2CFB9A7A-4AAF-4B6A-8CC8-540F64C3B45F}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NativeExports", "TestAssets\NativeExports\NativeExports.csproj", "{32FDA079-0E9F-4A36-ADA5-6593B67A54AC}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NativeExports", "TestAssets\NativeExports\NativeExports.csproj", "{32FDA079-0E9F-4A36-ADA5-6593B67A54AC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DllImportGenerator.IntegrationTests", "DllImportGenerator.IntegrationTests\DllImportGenerator.IntegrationTests.csproj", "{162C204A-ED59-4EF3-A5FA-E58CC06FAB4D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{69D56AC9-232B-4E76-B6C1-33A7B06B6855}"
EndProject
@@ -49,6 +51,10 @@ Global
{6FD4AF19-0CAA-413C-A2BD-C888AA2E8CFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6FD4AF19-0CAA-413C-A2BD-C888AA2E8CFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6FD4AF19-0CAA-413C-A2BD-C888AA2E8CFB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {162C204A-ED59-4EF3-A5FA-E58CC06FAB4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {162C204A-ED59-4EF3-A5FA-E58CC06FAB4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {162C204A-ED59-4EF3-A5FA-E58CC06FAB4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {162C204A-ED59-4EF3-A5FA-E58CC06FAB4D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/DllImportGenerator/TestAssets/NativeExports/ScalarOps.cs b/DllImportGenerator/TestAssets/NativeExports/Demo.cs
similarity index 84%
rename from DllImportGenerator/TestAssets/NativeExports/ScalarOps.cs
rename to DllImportGenerator/TestAssets/NativeExports/Demo.cs
index 4d2bb92006f6..6e82b412b6b7 100644
--- a/DllImportGenerator/TestAssets/NativeExports/ScalarOps.cs
+++ b/DllImportGenerator/TestAssets/NativeExports/Demo.cs
@@ -1,9 +1,8 @@
-using System;
-using System.Runtime.InteropServices;
+using System.Runtime.InteropServices;
namespace NativeExports
{
- public unsafe class ScalarOps
+ public static unsafe class Demo
{
[UnmanagedCallersOnly(EntryPoint = "sumi")]
public static int Sum(int a, int b)
diff --git a/DllImportGenerator/TestAssets/NativeExports/Handles.cs b/DllImportGenerator/TestAssets/NativeExports/Handles.cs
index fae57f242fe5..0cc2ab4f9fe9 100644
--- a/DllImportGenerator/TestAssets/NativeExports/Handles.cs
+++ b/DllImportGenerator/TestAssets/NativeExports/Handles.cs
@@ -1,16 +1,18 @@
using System.Collections.Generic;
using System.Runtime.InteropServices;
-
namespace NativeExports
{
public static unsafe class Handles
{
+ ///
+ /// Using in tests.
+ ///
private const nint InvalidHandle = -1;
private static nint LastHandle = 0;
- private static HashSet ActiveHandles = new HashSet();
+ private static readonly HashSet ActiveHandles = new HashSet();
[UnmanagedCallersOnly(EntryPoint = "alloc_handle")]
public static nint AllocateHandle()
@@ -18,18 +20,6 @@ public static nint AllocateHandle()
return AllocateHandleCore();
}
- private static nint AllocateHandleCore()
- {
- if (LastHandle == int.MaxValue)
- {
- return InvalidHandle;
- }
-
- nint newHandle = ++LastHandle;
- ActiveHandles.Add(newHandle);
- return newHandle;
- }
-
[UnmanagedCallersOnly(EntryPoint = "release_handle")]
public static byte ReleaseHandle(nint handle)
{
@@ -50,5 +40,17 @@ public static void ModifyHandle(nint* handle, byte newHandle)
*handle = AllocateHandleCore();
}
}
+
+ private static nint AllocateHandleCore()
+ {
+ if (LastHandle == int.MaxValue)
+ {
+ return InvalidHandle;
+ }
+
+ nint newHandle = ++LastHandle;
+ ActiveHandles.Add(newHandle);
+ return newHandle;
+ }
}
}
\ No newline at end of file
diff --git a/DllImportGenerator/readme.md b/DllImportGenerator/readme.md
index 9ba80ca33220..30e05076eb5c 100644
--- a/DllImportGenerator/readme.md
+++ b/DllImportGenerator/readme.md
@@ -1,24 +1,31 @@
# DllImport Generator
-See [P/Invoke source generator proposal](https://github.com/dotnet/runtime/blob/master/docs/design/features/source-generator-pinvokes.md) for design and goals.
+Work on this project can be tracked and discussed via the [official issue](https://github.com/dotnet/runtime/issues/43060) in `dotnet/runtime`. The [P/Invoke source generator proposal](https://github.com/dotnet/runtime/blob/master/docs/design/features/source-generator-pinvokes.md) contains additional details.
-## Additional work
+## Example
-Below are additional work items that are not presently captured in this repository.
+The [Demo project](./DllImportGenerator/Demo) is designed to be immediately consumable by everyone. It demonstrates a simple use case where the marshalling code is generated and a native function call with only [blittable types](https://docs.microsoft.com/dotnet/framework/interop/blittable-and-non-blittable-types) is made. A managed assembly with [native exports](./DllImportGenerator/TestAssets/NativeExports) is used in the P/Invoke scenario.
-### Required
+### Recommended scenarios:
+* Step into the `Demo` application and observe the generated code for the `Sum` functions.
+* Find the implementation of the `sumrefi` function and set a breakpoint. Run the debugger and explore the stack.
+* Add a new export in the `NativeExports` project and update the `Demo` application to call the new export.
+* Try the above scenarios when building in `Debug` or `Release`. Consider the differences.
-* Add `GeneratedDllImportAttribute` to the BCL. See [`GeneratedDllImportAttribute.cs`](./Ancillary.Interop/GeneratedDllImportAttribute.cs).
-* Add support for calling [`SetLastError()`](https://docs.microsoft.com/windows/win32/api/errhandlingapi/nf-errhandlingapi-setlasterror) from managed code with the expected semantics. During P/Invoke transitions the runtime manipulates the associated thread's error code and thus breaks `SetLastError()` semantics.
+## Designs
-* APIs to handle [`SafeHandle`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.safehandle) manipulation.
+- [Code generation pipeline](./designs/Pipeline.md)
+- [Struct Marshalling](./designs/StructMarshalling.md)
-### Optional
+## Workflow
-* A tool to compare the resulting IL from the generated source to that generated by the built-in IL Marshaller system. This would help with validation of what is being generated.
+All features of the [`dotnet` command line tool](https://docs.microsoft.com/dotnet/core/tools/) are supported for the respective project types (e.g. `build`, `run`, `test`). A consistent cross-platform inner dev loop with an IDE is available using [Visual Studio Code](https://code.visualstudio.com/) when appropriate .NET extensions are loaded.
-## Designs
+On Windows, loading the [solution](./DllImportGenerator.sln) in [Visual Studio](https://visualstudio.microsoft.com/) 2019 or later will enable the edit, build, debug inner dev loop. All features of Visual Studio are expected to operate correctly (e.g. Debugger, Test runner, Profiler).
-- [Code generation pipeline](./designs/Pipeline.md)
-- [Struct Marshalling](./designs/StructMarshalling.md)
+Most of the above options have [official tutorials](https://docs.microsoft.com/dotnet/core/tutorials/). It is an aim of this project to follow canonical workflows that are intuitive to all developers.
+
+### Testing assets
+
+This project has no explicit native build system and should remain that way. The [`DNNE`](https://github.com/AaronRobinsonMSFT/DNNE/) project is used to create native exports that can be called from the P/Invokes during testing.