From 42e8300130f891b7c67242e6f33b05a45ea3b09b Mon Sep 17 00:00:00 2001 From: Lucas Girouard-Stranks <519592+lithiumtoast@users.noreply.github.com> Date: Thu, 2 Jan 2025 14:51:16 -0500 Subject: [PATCH 1/8] Refactor test common code into C# library --- .github/workflows/release.yml | 2 +- src/cs/c2cs.sln | 9 ++++++- .../CBool.cs | 3 +++ .../CChar.cs | 3 +++ .../CString.cs | 3 +++ .../CStringWide.cs | 3 +++ .../CStrings.cs | 0 .../Interop.Runtime.csproj} | 0 src/cs/production/c2cs.Tool/c2cs.Tool.csproj | 22 +++++++++++++++- .../Assertions}/CSharpTestTypeAssertions.cs | 4 +-- .../Extensions.cs | 2 +- .../tests/c2cs.Tests.Common/GlobalUsings.cs | 7 ++++++ .../Helpers}/FileSystemHelper.cs | 4 +-- .../Model}/CSharpTestAbstractSyntaxTree.cs | 4 +-- .../Model}/CSharpTestCallingConvention.cs | 2 +- .../Model}/CSharpTestEnum.cs | 6 ++--- .../Model}/CSharpTestEnumValue.cs | 2 +- .../Model}/CSharpTestFunction.cs | 3 +-- .../Model}/CSharpTestFunctionParameter.cs | 2 +- .../CSharpTestFunctionParameterAssertions.cs | 2 +- .../Model}/CSharpTestMacroObject.cs | 2 +- .../Model}/CSharpTestStruct.cs | 3 +-- .../Model}/CSharpTestStructField.cs | 2 +- .../Model}/CSharpTestStructLayout.cs | 2 +- .../Model}/CSharpTestType.cs | 3 +-- .../c2cs.Tests.Common.csproj | 25 +++++++++++++++++++ .../tests/c2cs.Tests/Enums/enum_uint8/Test.cs | 2 -- .../c2cs.Tests/Enums/enum_week_day/Test.cs | 2 -- .../Functions/function_implicit_enum/Test.cs | 4 --- src/cs/tests/c2cs.Tests/GlobalUsings.cs | 2 ++ src/cs/tests/c2cs.Tests/TestHost.cs | 1 + .../tests/c2cs.Tests/WriteCSharpCodeTest.cs | 2 +- src/cs/tests/c2cs.Tests/c2cs.Tests.csproj | 12 ++------- 33 files changed, 98 insertions(+), 47 deletions(-) rename src/cs/production/{c2cs.Interop.Runtime => Interop.Runtime}/CBool.cs (98%) rename src/cs/production/{c2cs.Interop.Runtime => Interop.Runtime}/CChar.cs (98%) rename src/cs/production/{c2cs.Interop.Runtime => Interop.Runtime}/CString.cs (99%) rename src/cs/production/{c2cs.Interop.Runtime => Interop.Runtime}/CStringWide.cs (99%) rename src/cs/production/{c2cs.Interop.Runtime => Interop.Runtime}/CStrings.cs (100%) rename src/cs/production/{c2cs.Interop.Runtime/c2cs.Interop.Runtime.csproj => Interop.Runtime/Interop.Runtime.csproj} (100%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Assertions}/CSharpTestTypeAssertions.cs (97%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common}/Extensions.cs (98%) create mode 100644 src/cs/tests/c2cs.Tests.Common/GlobalUsings.cs rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Helpers}/FileSystemHelper.cs (96%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Model}/CSharpTestAbstractSyntaxTree.cs (95%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Model}/CSharpTestCallingConvention.cs (88%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Model}/CSharpTestEnum.cs (92%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Model}/CSharpTestEnumValue.cs (95%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Model}/CSharpTestFunction.cs (98%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Model}/CSharpTestFunctionParameter.cs (95%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Model}/CSharpTestFunctionParameterAssertions.cs (99%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Model}/CSharpTestMacroObject.cs (95%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Model}/CSharpTestStruct.cs (95%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Model}/CSharpTestStructField.cs (97%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Model}/CSharpTestStructLayout.cs (97%) rename src/cs/tests/{c2cs.Tests => c2cs.Tests.Common/Model}/CSharpTestType.cs (96%) create mode 100644 src/cs/tests/c2cs.Tests.Common/c2cs.Tests.Common.csproj diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a9b8306c..6f293684 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -51,7 +51,7 @@ jobs: dotnet-version: '9.x' - name: ".NET pack" - run: dotnet pack "./src/cs" --nologo --verbosity minimal --configuration Release -p:PackageVersion="${{ steps.set-version.outputs.VERSION }}" -p:RepositoryBranch="${{ github.head_ref || github.ref_name }}" -p:RepositoryCommit="${{ github.sha }}" + run: dotnet pack "./src/cs" --nologo --verbosity minimal --configuration Release /property:Version="${{ steps.set-version.outputs.VERSION }}" -p:PackageVersion="${{ steps.set-version.outputs.VERSION }}" -p:RepositoryBranch="${{ github.head_ref || github.ref_name }}" -p:RepositoryCommit="${{ github.sha }}" - name: "Upload packages to MyGet" if: github.event_name == 'workflow_dispatch' && github.event.inputs.pre-release == 'true' diff --git a/src/cs/c2cs.sln b/src/cs/c2cs.sln index 58e62fd7..09142ba7 100644 --- a/src/cs/c2cs.sln +++ b/src/cs/c2cs.sln @@ -14,10 +14,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "helloworld-bindgen", "examp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "c2cs.Tool", "production\c2cs.Tool\c2cs.Tool.csproj", "{1B67F4A2-24E6-43A6-A031-918DD44CD991}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "c2cs.Interop.Runtime", "production\c2cs.Interop.Runtime\c2cs.Interop.Runtime.csproj", "{DB492E65-25D9-44A0-86F4-ABB07283BEE7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Runtime", "production\Interop.Runtime\Interop.Runtime.csproj", "{DB492E65-25D9-44A0-86F4-ABB07283BEE7}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "helloworld-app", "examples\helloworld\helloworld-app\helloworld-app.csproj", "{EA3E3362-32A5-4395-BF56-39BDBE2B7CC9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "c2cs.Tests.Common", "tests\c2cs.Tests.Common\c2cs.Tests.Common.csproj", "{1AC16D87-0DB7-42AD-8CB9-4738D1B2D8D4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -44,6 +46,10 @@ Global {EA3E3362-32A5-4395-BF56-39BDBE2B7CC9}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA3E3362-32A5-4395-BF56-39BDBE2B7CC9}.Release|Any CPU.ActiveCfg = Release|Any CPU {EA3E3362-32A5-4395-BF56-39BDBE2B7CC9}.Release|Any CPU.Build.0 = Release|Any CPU + {1AC16D87-0DB7-42AD-8CB9-4738D1B2D8D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1AC16D87-0DB7-42AD-8CB9-4738D1B2D8D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1AC16D87-0DB7-42AD-8CB9-4738D1B2D8D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1AC16D87-0DB7-42AD-8CB9-4738D1B2D8D4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {1BE51A85-A187-46CC-A307-04A66316CD55} = {65B41709-3C9F-4556-83C8-A4380AC14E56} @@ -52,5 +58,6 @@ Global {1B67F4A2-24E6-43A6-A031-918DD44CD991} = {D5FE4F37-21B4-498E-B6B7-CB9DDBE5937A} {DB492E65-25D9-44A0-86F4-ABB07283BEE7} = {D5FE4F37-21B4-498E-B6B7-CB9DDBE5937A} {EA3E3362-32A5-4395-BF56-39BDBE2B7CC9} = {24028D61-CCE1-4893-9BD6-1D7C28563DC8} + {1AC16D87-0DB7-42AD-8CB9-4738D1B2D8D4} = {65B41709-3C9F-4556-83C8-A4380AC14E56} EndGlobalSection EndGlobal diff --git a/src/cs/production/c2cs.Interop.Runtime/CBool.cs b/src/cs/production/Interop.Runtime/CBool.cs similarity index 98% rename from src/cs/production/c2cs.Interop.Runtime/CBool.cs rename to src/cs/production/Interop.Runtime/CBool.cs index 5571222f..7b6ed5fb 100644 --- a/src/cs/production/c2cs.Interop.Runtime/CBool.cs +++ b/src/cs/production/Interop.Runtime/CBool.cs @@ -14,6 +14,9 @@ namespace Interop.Runtime; [StructLayout(LayoutKind.Sequential)] public readonly struct CBool : IEquatable { + /// + /// The value. + /// public readonly byte Value; private CBool(bool value) diff --git a/src/cs/production/c2cs.Interop.Runtime/CChar.cs b/src/cs/production/Interop.Runtime/CChar.cs similarity index 98% rename from src/cs/production/c2cs.Interop.Runtime/CChar.cs rename to src/cs/production/Interop.Runtime/CChar.cs index 5055a620..66a6a33d 100644 --- a/src/cs/production/c2cs.Interop.Runtime/CChar.cs +++ b/src/cs/production/Interop.Runtime/CChar.cs @@ -14,6 +14,9 @@ namespace Interop.Runtime; [StructLayout(LayoutKind.Sequential)] public readonly struct CChar : IEquatable, IEquatable { + /// + /// The value. + /// public readonly byte Value; private CChar(byte value) diff --git a/src/cs/production/c2cs.Interop.Runtime/CString.cs b/src/cs/production/Interop.Runtime/CString.cs similarity index 99% rename from src/cs/production/c2cs.Interop.Runtime/CString.cs rename to src/cs/production/Interop.Runtime/CString.cs index 4709f549..145a3ed8 100644 --- a/src/cs/production/c2cs.Interop.Runtime/CString.cs +++ b/src/cs/production/Interop.Runtime/CString.cs @@ -12,6 +12,9 @@ namespace Interop.Runtime; [StructLayout(LayoutKind.Sequential)] public readonly unsafe struct CString : IEquatable, IDisposable { + /// + /// The pointer. + /// public readonly IntPtr Pointer; /// diff --git a/src/cs/production/c2cs.Interop.Runtime/CStringWide.cs b/src/cs/production/Interop.Runtime/CStringWide.cs similarity index 99% rename from src/cs/production/c2cs.Interop.Runtime/CStringWide.cs rename to src/cs/production/Interop.Runtime/CStringWide.cs index f96e6a85..4905577b 100644 --- a/src/cs/production/c2cs.Interop.Runtime/CStringWide.cs +++ b/src/cs/production/Interop.Runtime/CStringWide.cs @@ -12,6 +12,9 @@ namespace Interop.Runtime; [StructLayout(LayoutKind.Sequential)] public readonly unsafe struct CStringWide : IEquatable { + /// + /// The pointer. + /// public readonly IntPtr Pointer; /// diff --git a/src/cs/production/c2cs.Interop.Runtime/CStrings.cs b/src/cs/production/Interop.Runtime/CStrings.cs similarity index 100% rename from src/cs/production/c2cs.Interop.Runtime/CStrings.cs rename to src/cs/production/Interop.Runtime/CStrings.cs diff --git a/src/cs/production/c2cs.Interop.Runtime/c2cs.Interop.Runtime.csproj b/src/cs/production/Interop.Runtime/Interop.Runtime.csproj similarity index 100% rename from src/cs/production/c2cs.Interop.Runtime/c2cs.Interop.Runtime.csproj rename to src/cs/production/Interop.Runtime/Interop.Runtime.csproj diff --git a/src/cs/production/c2cs.Tool/c2cs.Tool.csproj b/src/cs/production/c2cs.Tool/c2cs.Tool.csproj index 95f7cbf2..badab553 100644 --- a/src/cs/production/c2cs.Tool/c2cs.Tool.csproj +++ b/src/cs/production/c2cs.Tool/c2cs.Tool.csproj @@ -40,11 +40,31 @@ - + + + false + CBool.cs + + + false + CChar.cs + + + false + CString.cs + + + false + CStrings.cs + + + false + CStringWide.cs + diff --git a/src/cs/tests/c2cs.Tests/CSharpTestTypeAssertions.cs b/src/cs/tests/c2cs.Tests.Common/Assertions/CSharpTestTypeAssertions.cs similarity index 97% rename from src/cs/tests/c2cs.Tests/CSharpTestTypeAssertions.cs rename to src/cs/tests/c2cs.Tests.Common/Assertions/CSharpTestTypeAssertions.cs index b16cacbc..d4f1a3ab 100644 --- a/src/cs/tests/c2cs.Tests/CSharpTestTypeAssertions.cs +++ b/src/cs/tests/c2cs.Tests.Common/Assertions/CSharpTestTypeAssertions.cs @@ -1,11 +1,11 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. -using System; +using C2CS.Tests.Common.Model; using FluentAssertions.Execution; using FluentAssertions.Primitives; -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Assertions; #pragma warning disable SA1649 public static class CSharpTestTypeExtensions diff --git a/src/cs/tests/c2cs.Tests/Extensions.cs b/src/cs/tests/c2cs.Tests.Common/Extensions.cs similarity index 98% rename from src/cs/tests/c2cs.Tests/Extensions.cs rename to src/cs/tests/c2cs.Tests.Common/Extensions.cs index c410b01b..a444e5f9 100644 --- a/src/cs/tests/c2cs.Tests/Extensions.cs +++ b/src/cs/tests/c2cs.Tests.Common/Extensions.cs @@ -5,7 +5,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace C2CS.Tests; +namespace C2CS.Tests.Common; public static class Extensions { diff --git a/src/cs/tests/c2cs.Tests.Common/GlobalUsings.cs b/src/cs/tests/c2cs.Tests.Common/GlobalUsings.cs new file mode 100644 index 00000000..cdaf7604 --- /dev/null +++ b/src/cs/tests/c2cs.Tests.Common/GlobalUsings.cs @@ -0,0 +1,7 @@ +// Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. +// Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. + +global using System; +global using System.Collections.Immutable; +global using FluentAssertions; +global using Xunit; diff --git a/src/cs/tests/c2cs.Tests/FileSystemHelper.cs b/src/cs/tests/c2cs.Tests.Common/Helpers/FileSystemHelper.cs similarity index 96% rename from src/cs/tests/c2cs.Tests/FileSystemHelper.cs rename to src/cs/tests/c2cs.Tests.Common/Helpers/FileSystemHelper.cs index a010437b..8a5675a6 100644 --- a/src/cs/tests/c2cs.Tests/FileSystemHelper.cs +++ b/src/cs/tests/c2cs.Tests.Common/Helpers/FileSystemHelper.cs @@ -3,10 +3,10 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.IO; using System.IO.Abstractions; -using SearchOption = System.IO.SearchOption; -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Helpers; [ExcludeFromCodeCoverage] public class FileSystemHelper(IFileSystem fileSystem) diff --git a/src/cs/tests/c2cs.Tests/CSharpTestAbstractSyntaxTree.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestAbstractSyntaxTree.cs similarity index 95% rename from src/cs/tests/c2cs.Tests/CSharpTestAbstractSyntaxTree.cs rename to src/cs/tests/c2cs.Tests.Common/Model/CSharpTestAbstractSyntaxTree.cs index d3d0a97f..11a6708a 100644 --- a/src/cs/tests/c2cs.Tests/CSharpTestAbstractSyntaxTree.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestAbstractSyntaxTree.cs @@ -1,9 +1,7 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. -using System.Collections.Immutable; - -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Model; public sealed class CSharpTestAbstractSyntaxTree( #pragma warning disable CS9113 // Parameter is unread. diff --git a/src/cs/tests/c2cs.Tests/CSharpTestCallingConvention.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestCallingConvention.cs similarity index 88% rename from src/cs/tests/c2cs.Tests/CSharpTestCallingConvention.cs rename to src/cs/tests/c2cs.Tests.Common/Model/CSharpTestCallingConvention.cs index 362c2d9c..b5557483 100644 --- a/src/cs/tests/c2cs.Tests/CSharpTestCallingConvention.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestCallingConvention.cs @@ -1,7 +1,7 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Model; public enum CSharpTestCallingConvention { diff --git a/src/cs/tests/c2cs.Tests/CSharpTestEnum.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestEnum.cs similarity index 92% rename from src/cs/tests/c2cs.Tests/CSharpTestEnum.cs rename to src/cs/tests/c2cs.Tests.Common/Model/CSharpTestEnum.cs index bbba9917..d70f669d 100644 --- a/src/cs/tests/c2cs.Tests/CSharpTestEnum.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestEnum.cs @@ -1,15 +1,13 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. -using System.Collections.Immutable; -using JetBrains.Annotations; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Model; + #pragma warning disable CA1036 -[PublicAPI] public class CSharpTestEnum { public string Name { get; } diff --git a/src/cs/tests/c2cs.Tests/CSharpTestEnumValue.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestEnumValue.cs similarity index 95% rename from src/cs/tests/c2cs.Tests/CSharpTestEnumValue.cs rename to src/cs/tests/c2cs.Tests.Common/Model/CSharpTestEnumValue.cs index 0c3c1e63..9ffb3d54 100644 --- a/src/cs/tests/c2cs.Tests/CSharpTestEnumValue.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestEnumValue.cs @@ -3,7 +3,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Model; public class CSharpTestEnumValue { diff --git a/src/cs/tests/c2cs.Tests/CSharpTestFunction.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestFunction.cs similarity index 98% rename from src/cs/tests/c2cs.Tests/CSharpTestFunction.cs rename to src/cs/tests/c2cs.Tests.Common/Model/CSharpTestFunction.cs index f87ff610..ed6bfad8 100644 --- a/src/cs/tests/c2cs.Tests/CSharpTestFunction.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestFunction.cs @@ -1,11 +1,10 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. -using System.Collections.Immutable; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Model; public class CSharpTestFunction { diff --git a/src/cs/tests/c2cs.Tests/CSharpTestFunctionParameter.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestFunctionParameter.cs similarity index 95% rename from src/cs/tests/c2cs.Tests/CSharpTestFunctionParameter.cs rename to src/cs/tests/c2cs.Tests.Common/Model/CSharpTestFunctionParameter.cs index 4a62ef72..f8fdcff7 100644 --- a/src/cs/tests/c2cs.Tests/CSharpTestFunctionParameter.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestFunctionParameter.cs @@ -4,7 +4,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Model; public class CSharpTestFunctionParameter { diff --git a/src/cs/tests/c2cs.Tests/CSharpTestFunctionParameterAssertions.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestFunctionParameterAssertions.cs similarity index 99% rename from src/cs/tests/c2cs.Tests/CSharpTestFunctionParameterAssertions.cs rename to src/cs/tests/c2cs.Tests.Common/Model/CSharpTestFunctionParameterAssertions.cs index b244bb6f..7738b633 100644 --- a/src/cs/tests/c2cs.Tests/CSharpTestFunctionParameterAssertions.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestFunctionParameterAssertions.cs @@ -5,7 +5,7 @@ using FluentAssertions.Execution; using FluentAssertions.Primitives; -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Model; #pragma warning disable SA1649 public static class CSharpTestFunctionParameterExtensions diff --git a/src/cs/tests/c2cs.Tests/CSharpTestMacroObject.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestMacroObject.cs similarity index 95% rename from src/cs/tests/c2cs.Tests/CSharpTestMacroObject.cs rename to src/cs/tests/c2cs.Tests.Common/Model/CSharpTestMacroObject.cs index 0bb44ea8..bce5ed31 100644 --- a/src/cs/tests/c2cs.Tests/CSharpTestMacroObject.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestMacroObject.cs @@ -3,7 +3,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Model; public class CSharpTestMacroObject { diff --git a/src/cs/tests/c2cs.Tests/CSharpTestStruct.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStruct.cs similarity index 95% rename from src/cs/tests/c2cs.Tests/CSharpTestStruct.cs rename to src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStruct.cs index 7d9c83d1..5235068e 100644 --- a/src/cs/tests/c2cs.Tests/CSharpTestStruct.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStruct.cs @@ -1,10 +1,9 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. -using System.Collections.Immutable; using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Model; public class CSharpTestStruct { diff --git a/src/cs/tests/c2cs.Tests/CSharpTestStructField.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructField.cs similarity index 97% rename from src/cs/tests/c2cs.Tests/CSharpTestStructField.cs rename to src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructField.cs index 026f70ec..9d5be359 100644 --- a/src/cs/tests/c2cs.Tests/CSharpTestStructField.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructField.cs @@ -4,7 +4,7 @@ using System.Globalization; using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Model; public class CSharpTestStructField { diff --git a/src/cs/tests/c2cs.Tests/CSharpTestStructLayout.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructLayout.cs similarity index 97% rename from src/cs/tests/c2cs.Tests/CSharpTestStructLayout.cs rename to src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructLayout.cs index 307916cf..35fd349d 100644 --- a/src/cs/tests/c2cs.Tests/CSharpTestStructLayout.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructLayout.cs @@ -4,7 +4,7 @@ using System.Globalization; using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Model; public class CSharpTestStructLayout { diff --git a/src/cs/tests/c2cs.Tests/CSharpTestType.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestType.cs similarity index 96% rename from src/cs/tests/c2cs.Tests/CSharpTestType.cs rename to src/cs/tests/c2cs.Tests.Common/Model/CSharpTestType.cs index a56a07fc..41d5746d 100644 --- a/src/cs/tests/c2cs.Tests/CSharpTestType.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestType.cs @@ -1,10 +1,9 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. -using System; using Microsoft.CodeAnalysis; -namespace C2CS.Tests; +namespace C2CS.Tests.Common.Model; public class CSharpTestType { diff --git a/src/cs/tests/c2cs.Tests.Common/c2cs.Tests.Common.csproj b/src/cs/tests/c2cs.Tests.Common/c2cs.Tests.Common.csproj new file mode 100644 index 00000000..6a184f09 --- /dev/null +++ b/src/cs/tests/c2cs.Tests.Common/c2cs.Tests.Common.csproj @@ -0,0 +1,25 @@ + + + + + net9.0 + enable + false + C2CS.Tests.Common + false + en + false + true + + + + + + + + + + + + + diff --git a/src/cs/tests/c2cs.Tests/Enums/enum_uint8/Test.cs b/src/cs/tests/c2cs.Tests/Enums/enum_uint8/Test.cs index 8b459923..cd1148b0 100644 --- a/src/cs/tests/c2cs.Tests/Enums/enum_uint8/Test.cs +++ b/src/cs/tests/c2cs.Tests/Enums/enum_uint8/Test.cs @@ -1,8 +1,6 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. -#pragma warning disable CA1707 - namespace C2CS.Tests.Enums.enum_uint8; public class Test : WriteCSharpCodeTest diff --git a/src/cs/tests/c2cs.Tests/Enums/enum_week_day/Test.cs b/src/cs/tests/c2cs.Tests/Enums/enum_week_day/Test.cs index d43bb740..a3457ce3 100644 --- a/src/cs/tests/c2cs.Tests/Enums/enum_week_day/Test.cs +++ b/src/cs/tests/c2cs.Tests/Enums/enum_week_day/Test.cs @@ -1,8 +1,6 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. -#pragma warning disable CA1707 - namespace C2CS.Tests.Enums.enum_week_day; public class Test : WriteCSharpCodeTest diff --git a/src/cs/tests/c2cs.Tests/Functions/function_implicit_enum/Test.cs b/src/cs/tests/c2cs.Tests/Functions/function_implicit_enum/Test.cs index 681b98d7..3e630007 100644 --- a/src/cs/tests/c2cs.Tests/Functions/function_implicit_enum/Test.cs +++ b/src/cs/tests/c2cs.Tests/Functions/function_implicit_enum/Test.cs @@ -1,10 +1,6 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. -using System; - -#pragma warning disable CA1707 - namespace C2CS.Tests.Functions.function_implicit_enum; public class Test : WriteCSharpCodeTest diff --git a/src/cs/tests/c2cs.Tests/GlobalUsings.cs b/src/cs/tests/c2cs.Tests/GlobalUsings.cs index 4356a1f1..85854051 100644 --- a/src/cs/tests/c2cs.Tests/GlobalUsings.cs +++ b/src/cs/tests/c2cs.Tests/GlobalUsings.cs @@ -1,6 +1,8 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. +global using C2CS.Tests.Common.Assertions; +global using C2CS.Tests.Common.Model; global using FluentAssertions; global using Xunit; diff --git a/src/cs/tests/c2cs.Tests/TestHost.cs b/src/cs/tests/c2cs.Tests/TestHost.cs index c9b01763..a3cc489a 100644 --- a/src/cs/tests/c2cs.Tests/TestHost.cs +++ b/src/cs/tests/c2cs.Tests/TestHost.cs @@ -3,6 +3,7 @@ using System; using C2CS.BuildCLibrary; +using C2CS.Tests.Common.Helpers; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; diff --git a/src/cs/tests/c2cs.Tests/WriteCSharpCodeTest.cs b/src/cs/tests/c2cs.Tests/WriteCSharpCodeTest.cs index f200591f..fd43a2be 100644 --- a/src/cs/tests/c2cs.Tests/WriteCSharpCodeTest.cs +++ b/src/cs/tests/c2cs.Tests/WriteCSharpCodeTest.cs @@ -4,10 +4,10 @@ using System; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; -using System.Globalization; using System.IO.Abstractions; using bottlenoselabs.Common; using C2CS.GenerateCSharpCode; +using C2CS.Tests.Common.Helpers; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; diff --git a/src/cs/tests/c2cs.Tests/c2cs.Tests.csproj b/src/cs/tests/c2cs.Tests/c2cs.Tests.csproj index 4febb5c6..36cdb513 100644 --- a/src/cs/tests/c2cs.Tests/c2cs.Tests.csproj +++ b/src/cs/tests/c2cs.Tests/c2cs.Tests.csproj @@ -15,10 +15,9 @@ - - + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -32,6 +31,7 @@ + @@ -42,12 +42,4 @@ - - - - - - - - From 873e2c5f835dbfd4e3a0c503b88ca8564915a722 Mon Sep 17 00:00:00 2001 From: Lucas Girouard-Stranks <519592+lithiumtoast@users.noreply.github.com> Date: Fri, 3 Jan 2025 13:47:46 -0500 Subject: [PATCH 2/8] Update README.md --- docs/README.md | 32 +++++++++++-------- .../BaseGenerator.cs} | 2 +- .../GeneratorAliasType.cs} | 7 ++-- .../GeneratorEnum.cs} | 6 ++-- .../GeneratorFunction.cs} | 6 ++-- .../GeneratorFunctionPointer.cs} | 7 ++-- .../GeneratorMacroObject.cs} | 6 ++-- .../GeneratorOpaqueType.cs} | 6 ++-- .../GeneratorStruct.cs} | 6 ++-- .../RoslynExtensions.cs} | 3 +- 10 files changed, 41 insertions(+), 40 deletions(-) rename src/cs/production/c2cs.Tool/GenerateCSharpCode/{CodeGeneratorNode.cs => Generators/BaseGenerator.cs} (95%) rename src/cs/production/c2cs.Tool/GenerateCSharpCode/{CodeGeneratorNodeAliasType.cs => Generators/GeneratorAliasType.cs} (87%) rename src/cs/production/c2cs.Tool/GenerateCSharpCode/{CodeGeneratorNodeEnum.cs => Generators/GeneratorEnum.cs} (91%) rename src/cs/production/c2cs.Tool/GenerateCSharpCode/{CodeGeneratorNodeFunction.cs => Generators/GeneratorFunction.cs} (96%) rename src/cs/production/c2cs.Tool/GenerateCSharpCode/{CodeGeneratorNodeFunctionPointer.cs => Generators/GeneratorFunctionPointer.cs} (94%) rename src/cs/production/c2cs.Tool/GenerateCSharpCode/{CodeGeneratorNodeMacroObject.cs => Generators/GeneratorMacroObject.cs} (80%) rename src/cs/production/c2cs.Tool/GenerateCSharpCode/{CodeGeneratorNodeOpaqueType.cs => Generators/GeneratorOpaqueType.cs} (80%) rename src/cs/production/c2cs.Tool/GenerateCSharpCode/{CodeGeneratorNodeStruct.cs => Generators/GeneratorStruct.cs} (96%) rename src/cs/tests/c2cs.Tests.Common/{Extensions.cs => Extensions/RoslynExtensions.cs} (98%) diff --git a/docs/README.md b/docs/README.md index d5e7dafa..0bce1cbe 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,10 +9,10 @@ - [How to use `C2CS`](#how-to-use-c2cs) - [Installing and using `c2ffi`](#installing-and-using-c2ffi) - [Execute `c2cs`](#execute-c2cs) - - [How to use `C2CS.Runtime`](#how-to-use-c2csruntime) + - [How to use the `Interop.Runtime`](#how-to-use-the-interopruntime) - [Building `C2CS` from source](#building-c2cs-from-source) - [Prerequisites](#prerequisites) - - [Visual Studio / Rider / MonoDevelop](#visual-studio--rider--monodevelop) + - [Visual Studio / Rider](#visual-studio--rider) - [Command Line Interface (CLI)](#command-line-interface-cli) - [Debugging `C2CS` from source](#debugging-c2cs-from-source) - [Debugging using logging](#debugging-using-logging) @@ -29,7 +29,7 @@ See [LESSONS-LEARNED.md](./LESSONS-LEARNED.md). ## Installing `C2CS` -`C2CS` is distributed as a NuGet tool. To get started, the .NET 8 software development kit (SDK) is required. +`C2CS` is distributed as a NuGet tool. To get started, the .NET 9 software development kit (SDK) is required. ### Latest release of `C2CS` @@ -51,31 +51,35 @@ dotnet nuget locals all --clear ## How to use `C2CS` -To generate C# bindings for a C library you need to install and use the `c2ffi` tool and setup a couple configuration files. See the [`helloworld`](../src/cs/examples/helloworld/) example projects for an example. +To generate C# bindings for a C library you need to first install and use the `c2ffi` tool. Then setup a couple configuration files. See the [`helloworld-bindgen`](../src/cs/examples/helloworld/helloworld-bindgen) example projects for an example of these configuration files. ### Installing and using `c2ffi` See the auxiliary project `Getting Started` section: https://github.com/bottlenoselabs/c2ffi#getting-started. -You should extract all the platform specific FFIs you wish to have as target platforms. See the [`helloworld-compile-c-library-and-generate-bindings`](../src/cs/examples/helloworld/helloworld-compile-c-library-and-generate-bindings/) for example configuration files for Windows, macOS, and Linux platforms. +You should extract all the platform specific FFIs you wish to have as target platforms using `c2ffi extract --config ...`. See the [`helloworld-bindgen/config-extract.json`](../src/cs/examples/helloworld/helloworld-bindgen/config-extract.json) for example configuration file for Windows, macOS, and Linux platforms. -Once all the platform FFIs are extracted to a directory, merge them together into a cross-platform FFI using `c2ffi merge` option. +Once all the platform FFIs are extracted to a directory, merge them together into a cross-platform FFI using `c2ffi merge --inputDirectoryPath ... --outputFilePath ...` option. + +See the [`helloworld-bindgen`]([`helloworld-bindgen`](../src/cs/examples/helloworld/helloworld-bindgen/Program.cs).) C# program for example of using `c2ffi` from command line. Once you have a cross-platform FFI `.json` file, you are ready to use `c2cs`. ### Execute `c2cs` -Run `c2cs --config` from terminal specifying a configuration file. See the [`config-generate-cs.json`](/src/cs/examples/helloworld/helloworld-compile-c-library-and-generate-bindings/config-generate-cs.json) for an example in the `helloworld-compile-c-library-and-generate-bindings` example. +Run `c2cs --config ...` from terminal specifying a configuration file. See the [`config-generate-cs.json`](../src/cs/examples/helloworld/helloworld-bindgen/config-generate-cs.json) for an example configuration `.json` file. + +## How to use the `Interop.Runtime` -## How to use `C2CS.Runtime` +The [`Interop.Runtime`](../src/cs/examples/helloworld/helloworld-app/Generated/Runtime.g.cs) C# code is by default generated to a new file as `Runtime.g.cs`. The `Interop.Runtime` namespace contains helper structs, methods, and other kind of "glue" that make interoperability with C in C# easier and more idiomatic. -The `C2CS.Runtime` C# code is directly added to the bottom of the generated bindings in a class named `Runtime` with a C# region named `C2CS.Runtime`. The `Runtime` static class contains helper structs, methods, and other kind of "glue" that make interoperability with C in C# easier and more idiomatic. +See the [HelloWorld example](src/cs/examples/helloworld/helloworld-app/Program.cs) for C# code that uses and explains how to use `Interop.Runtime`. ## Building `C2CS` from source ### Prerequisites -1. Install [.NET 8 SDK](https://dotnet.microsoft.com/download). +1. Install [.NET 9 SDK](https://dotnet.microsoft.com/download). 2. Install build tools for C/C++. - Windows: 1. Install Git Bash. (Usually installed with Git for Windows: https://git-scm.com/downloads.) @@ -87,9 +91,9 @@ The `C2CS.Runtime` C# code is directly added to the bottom of the generated bind 4. Install CMake: ```brew install cmake``` - Linux: 1. Install the software build tools for your distro including GCC, Clang, and CMake. -3. Clone the repository with submodules: `git clone --recurse-submodules https://github.com/lithiumtoast/c2cs.git`. +3. Clone the repository with submodules: `git clone --recurse-submodules https://github.com/bottlenoselabs/c2cs.git`. -### Visual Studio / Rider / MonoDevelop +### Visual Studio / Rider Open `./C2CS.sln` @@ -131,5 +135,5 @@ Here you will find examples of C libraries being demonstrated with `C2CS` as smo Hello world example of callings C functions from C#. This is meant to be minimalistic to demonstrate the minimum required things to get this working. -1. Run the C# project [`helloworld-compile-c-library-and-generate-bindings`](../src/cs/examples/helloworld/helloworld-compile-c-library-and-generate-bindings/Program.cs). This builds the example shared library and generate the bindings for the [`my_c_library`](../src/cs/examples/helloworld/helloworld-compile-c-library-and-generate-bindings/my_c_library/) C project. The C# bindings will be written to [`my_c_library.cs`](../src/cs/examples/helloworld/helloworld-app/Generated/my_c_library.gen.cs). -2. Run the C# project [`helloworld-cs`](../src/cs/examples/helloworld/helloworld-app/Program.cs). You should see output to the console of C functions being called from C#. +1. Run the C# project [`helloworld-bindgen`](../src/cs/examples/helloworld/helloworld-bindgen/Program.cs). This builds the example shared C library and generate the bindings for the [`my_c_library`](../src/cs/examples/helloworld/helloworld-bindgen/my_c_library) C project. The C# bindings will be written to [`my_c_library.g.cs`](../src/cs/examples/helloworld/helloworld-app/Generated/my_c_library.g.cs). +2. Run the C# project [`helloworld-app`](../src/cs/examples/helloworld/helloworld-app/Program.cs). You should see output to the console of C functions being called from C#. diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNode.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/BaseGenerator.cs similarity index 95% rename from src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNode.cs rename to src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/BaseGenerator.cs index e9e796df..35e76508 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNode.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/BaseGenerator.cs @@ -4,7 +4,7 @@ using c2ffi.Data.Nodes; using Microsoft.Extensions.Logging; -namespace C2CS.GenerateCSharpCode; +namespace C2CS.GenerateCSharpCode.Generators; public abstract class CodeGeneratorNode(ILogger logger) { diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeAliasType.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorAliasType.cs similarity index 87% rename from src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeAliasType.cs rename to src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorAliasType.cs index 83de252f..9c4709f8 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeAliasType.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorAliasType.cs @@ -1,16 +1,15 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. -using System; using c2ffi.Data.Nodes; using JetBrains.Annotations; using Microsoft.Extensions.Logging; -namespace C2CS.GenerateCSharpCode; +namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public class CodeGeneratorNodeAliasType(ILogger logger) - : CodeGeneratorNode(logger) +public class GeneratorNodeAliasType(ILogger logger) + : BaseGenerator(logger) { protected override string GenerateCode( string nameCSharp, CodeGeneratorContext context, CTypeAlias node) diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeEnum.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorEnum.cs similarity index 91% rename from src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeEnum.cs rename to src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorEnum.cs index e09cd926..48a46e89 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeEnum.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorEnum.cs @@ -7,11 +7,11 @@ using JetBrains.Annotations; using Microsoft.Extensions.Logging; -namespace C2CS.GenerateCSharpCode; +namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public class CodeGeneratorNodeEnum(ILogger logger) - : CodeGeneratorNode(logger) +public class GeneratorNodeEnum(ILogger logger) + : BaseGenerator(logger) { protected override string GenerateCode( string nameCSharp, diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeFunction.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunction.cs similarity index 96% rename from src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeFunction.cs rename to src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunction.cs index 6bdfe236..e586323a 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeFunction.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunction.cs @@ -9,11 +9,11 @@ using JetBrains.Annotations; using Microsoft.Extensions.Logging; -namespace C2CS.GenerateCSharpCode; +namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public class CodeGeneratorNodeFunction(ILogger logger) - : CodeGeneratorNode(logger) +public class GeneratorNodeFunction(ILogger logger) + : BaseGenerator(logger) { protected override string GenerateCode( string nameCSharp, diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeFunctionPointer.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunctionPointer.cs similarity index 94% rename from src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeFunctionPointer.cs rename to src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunctionPointer.cs index 5f0c433c..fd134e66 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeFunctionPointer.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunctionPointer.cs @@ -1,18 +1,17 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. -using System; using System.Collections.Immutable; using System.Text; using c2ffi.Data.Nodes; using JetBrains.Annotations; using Microsoft.Extensions.Logging; -namespace C2CS.GenerateCSharpCode; +namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public sealed class CodeGeneratorNodeFunctionPointer(ILogger logger) - : CodeGeneratorNode(logger) +public sealed class GeneratorNodeFunctionPointer(ILogger logger) + : BaseGenerator(logger) { protected override string GenerateCode( string nameCSharp, CodeGeneratorContext context, CFunctionPointer node) diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeMacroObject.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorMacroObject.cs similarity index 80% rename from src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeMacroObject.cs rename to src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorMacroObject.cs index ec3c83b0..ffabcc2c 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeMacroObject.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorMacroObject.cs @@ -5,11 +5,11 @@ using JetBrains.Annotations; using Microsoft.Extensions.Logging; -namespace C2CS.GenerateCSharpCode; +namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public class CodeGeneratorNodeMacroObject(ILogger logger) - : CodeGeneratorNode(logger) +public class GeneratorNodeMacroObject(ILogger logger) + : BaseGenerator(logger) { protected override string GenerateCode( string nameCSharp, CodeGeneratorContext context, CMacroObject node) diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeOpaqueType.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorOpaqueType.cs similarity index 80% rename from src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeOpaqueType.cs rename to src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorOpaqueType.cs index 20509f62..c9523dc9 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeOpaqueType.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorOpaqueType.cs @@ -5,11 +5,11 @@ using JetBrains.Annotations; using Microsoft.Extensions.Logging; -namespace C2CS.GenerateCSharpCode; +namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public class CodeGeneratorNodeOpaqueType(ILogger logger) - : CodeGeneratorNode(logger) +public class GeneratorNodeOpaqueType(ILogger logger) + : BaseGenerator(logger) { protected override string GenerateCode( string nameCSharp, CodeGeneratorContext context, COpaqueType node) diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeStruct.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorStruct.cs similarity index 96% rename from src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeStruct.cs rename to src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorStruct.cs index 0827fabb..376edc25 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorNodeStruct.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorStruct.cs @@ -6,11 +6,11 @@ using JetBrains.Annotations; using Microsoft.Extensions.Logging; -namespace C2CS.GenerateCSharpCode; +namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public class CodeGeneratorNodeStruct(ILogger logger) - : CodeGeneratorNode(logger) +public class GeneratorNodeStruct(ILogger logger) + : BaseGenerator(logger) { protected override string GenerateCode(string nameCSharp, CodeGeneratorContext context, CRecord record) { diff --git a/src/cs/tests/c2cs.Tests.Common/Extensions.cs b/src/cs/tests/c2cs.Tests.Common/Extensions/RoslynExtensions.cs similarity index 98% rename from src/cs/tests/c2cs.Tests.Common/Extensions.cs rename to src/cs/tests/c2cs.Tests.Common/Extensions/RoslynExtensions.cs index a444e5f9..664a068f 100644 --- a/src/cs/tests/c2cs.Tests.Common/Extensions.cs +++ b/src/cs/tests/c2cs.Tests.Common/Extensions/RoslynExtensions.cs @@ -1,13 +1,12 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. -using System; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace C2CS.Tests.Common; -public static class Extensions +public static class RoslynExtensions { public static AttributeSyntax? TryGetAttribute(this MemberDeclarationSyntax syntaxNode, string name) { From 0247d9209e3ede1d357dac184633759d4139c1a5 Mon Sep 17 00:00:00 2001 From: Lucas Girouard-Stranks <519592+lithiumtoast@users.noreply.github.com> Date: Fri, 3 Jan 2025 13:50:16 -0500 Subject: [PATCH 3/8] `CString` support for UTF-8 string literals --- .../Generated/AssemblyAttributes.g.cs | 4 +- .../helloworld-app/Generated/Runtime.g.cs | 60 ++++++++++++++++++- .../Generated/my_c_library.g.cs | 2 +- .../helloworld/helloworld-app/Program.cs | 24 ++++++-- src/cs/production/Interop.Runtime/CString.cs | 46 +++++++++++++- 5 files changed, 122 insertions(+), 14 deletions(-) diff --git a/src/cs/examples/helloworld/helloworld-app/Generated/AssemblyAttributes.g.cs b/src/cs/examples/helloworld/helloworld-app/Generated/AssemblyAttributes.g.cs index 69617cbf..04f7b5de 100644 --- a/src/cs/examples/helloworld/helloworld-app/Generated/AssemblyAttributes.g.cs +++ b/src/cs/examples/helloworld/helloworld-app/Generated/AssemblyAttributes.g.cs @@ -1,6 +1,6 @@ // -// This code was generated by the following tool on 2025-01-01 22:44:49 GMT-05:00: -// https://github.com/bottlenoselabs/c2cs (v2025-01-01 22:44:49 GMT-05:00) +// This code was generated by the following tool on 2025-01-03 12:59:48 GMT-05:00: +// https://github.com/bottlenoselabs/c2cs (v2025-01-03 12:59:48 GMT-05:00) // // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. // diff --git a/src/cs/examples/helloworld/helloworld-app/Generated/Runtime.g.cs b/src/cs/examples/helloworld/helloworld-app/Generated/Runtime.g.cs index 2c8b98fe..850727db 100644 --- a/src/cs/examples/helloworld/helloworld-app/Generated/Runtime.g.cs +++ b/src/cs/examples/helloworld/helloworld-app/Generated/Runtime.g.cs @@ -1,5 +1,5 @@ // -// This code was generated by the following tool on 2025-01-01 22:44:49 GMT-05:00: +// This code was generated by the following tool on 2025-01-03 12:59:48 GMT-05:00: // https://github.com/bottlenoselabs/c2cs (v0.0.0.0) // // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. @@ -22,6 +22,9 @@ namespace Interop.Runtime; [StructLayout(LayoutKind.Sequential)] public readonly struct CBool : IEquatable { + /// + /// The value. + /// public readonly byte Value; private CBool(bool value) @@ -134,6 +137,9 @@ public static bool Equals(CBool left, CBool right) [StructLayout(LayoutKind.Sequential)] public readonly struct CChar : IEquatable, IEquatable { + /// + /// The value. + /// public readonly byte Value; private CChar(byte value) @@ -251,6 +257,9 @@ public static bool Equals(CChar left, CChar right) [StructLayout(LayoutKind.Sequential)] public readonly unsafe struct CString : IEquatable, IDisposable { + /// + /// The pointer. + /// public readonly IntPtr Pointer; /// @@ -258,6 +267,22 @@ public static bool Equals(CChar left, CChar right) /// public bool IsNull => Pointer == IntPtr.Zero; +#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER + /// + /// Initializes a new instance of the struct. + /// + /// The span. + public CString(ReadOnlySpan value) + { +#pragma warning disable CS8500 + fixed (byte* pointer = value) + { + Pointer = (IntPtr)pointer; + } +#pragma warning restore CS8500 + } +#endif + /// /// Initializes a new instance of the struct. /// @@ -306,7 +331,7 @@ public static explicit operator CString(IntPtr value) } /// - /// Performs an explicit conversion from an to a . + /// Performs a conversion from an to a . /// /// The pointer value. /// @@ -341,6 +366,32 @@ public static CString From(byte* value) return new CString((IntPtr)value); } +#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER + /// + /// Performs an explicit conversion from a to a . + /// + /// The pointer. + /// + /// The resulting . + /// + public static explicit operator CString(ReadOnlySpan value) + { + return new CString(value); + } + + /// + /// Performs a conversion from a to a . + /// + /// The pointer value. + /// + /// The resulting . + /// + public static CString FromReadOnlySpan(ReadOnlySpan value) + { + return new CString(value); + } +#endif + /// /// Performs an implicit conversion from a to a . /// @@ -354,7 +405,7 @@ public static implicit operator IntPtr(CString value) } /// - /// Performs an implicit conversion from a to a . + /// Performs a conversion from a to a . /// /// The pointer. /// @@ -531,6 +582,9 @@ public static unsafe class CStrings [StructLayout(LayoutKind.Sequential)] public readonly unsafe struct CStringWide : IEquatable { + /// + /// The pointer. + /// public readonly IntPtr Pointer; /// diff --git a/src/cs/examples/helloworld/helloworld-app/Generated/my_c_library.g.cs b/src/cs/examples/helloworld/helloworld-app/Generated/my_c_library.g.cs index 20178f25..3c3b65ce 100644 --- a/src/cs/examples/helloworld/helloworld-app/Generated/my_c_library.g.cs +++ b/src/cs/examples/helloworld/helloworld-app/Generated/my_c_library.g.cs @@ -1,5 +1,5 @@ // -// This code was generated by the following tool on 2025-01-01 22:44:49 GMT-05:00: +// This code was generated by the following tool on 2025-01-03 12:59:48 GMT-05:00: // https://github.com/bottlenoselabs/c2cs (v0.0.0.0) // // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. diff --git a/src/cs/examples/helloworld/helloworld-app/Program.cs b/src/cs/examples/helloworld/helloworld-app/Program.cs index 4ea66f49..ce1292e0 100644 --- a/src/cs/examples/helloworld/helloworld-app/Program.cs +++ b/src/cs/examples/helloworld/helloworld-app/Program.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. using System; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Interop.Runtime; using static helloworld.my_c_library; @@ -12,9 +13,22 @@ private static unsafe void Main() { hw_hello_world(); - var cString1 = (CString)"Hello world from C#!"; + // NOTE: If you apply the `u8`, it's a UTF-8 string literal and does not allocate the string on the heap! + // See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types#utf-8-string-literals + var cString1 = (CString)"Hello world from C# using UTF-8 string literal! No need to free this string!"u8; hw_pass_string(cString1); - Marshal.FreeHGlobal(cString1); + + // NOTE: If you don't apply the `u8` it's a UTF-16 string which needs to be converted to UTF-8 and allocated. + // This is done by calling `CString.FromString` or using the explicit CString conversion operator. + // You additionally need to call `Marshal.FreeHGlobal()` when you are done with it or you have a memory leak! + var cString2 = CString.FromString("Hello world from C# using UTF-16 converted UTF-8 and allocated! Don't forgot to free this string!"); + hw_pass_string(cString2); + Marshal.FreeHGlobal(cString2); + + // NOTE: You can also use `using` syntax so you don't forgot to call `Marshal.FreeHGlobal()` at the scope end. + // Just don't use `using` syntax when using UTF-8 string literals or your app will crash! + using var cString3 = (CString)"Hello world again from C# using UTF-16 converted UTF-8 and allocated! Don't forgot to free this string!"; + hw_pass_string(cString3); hw_pass_integers_by_value(65449, -255, 24242); @@ -28,9 +42,8 @@ private static unsafe void Main() #else var functionPointer = new FnPtr_CString_Void(Callback); #endif - var cString2 = (CString)"Hello from callback!"; - hw_invoke_callback(functionPointer, cString2); - Marshal.FreeHGlobal(cString2); + using var cStringCallback = (CString)"Hello from callback!"; + hw_invoke_callback(functionPointer, cStringCallback); } #if NET5_0_OR_GREATER @@ -39,7 +52,6 @@ private static unsafe void Main() private static void Callback(CString param) { // This C# function is called from C - // Get the string and print it var str = param.ToString(); Console.WriteLine(str); diff --git a/src/cs/production/Interop.Runtime/CString.cs b/src/cs/production/Interop.Runtime/CString.cs index 145a3ed8..8e8543c3 100644 --- a/src/cs/production/Interop.Runtime/CString.cs +++ b/src/cs/production/Interop.Runtime/CString.cs @@ -22,6 +22,22 @@ namespace Interop.Runtime; /// public bool IsNull => Pointer == IntPtr.Zero; +#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER + /// + /// Initializes a new instance of the struct. + /// + /// The span. + public CString(ReadOnlySpan value) + { +#pragma warning disable CS8500 + fixed (byte* pointer = value) + { + Pointer = (IntPtr)pointer; + } +#pragma warning restore CS8500 + } +#endif + /// /// Initializes a new instance of the struct. /// @@ -70,7 +86,7 @@ public static explicit operator CString(IntPtr value) } /// - /// Performs an explicit conversion from an to a . + /// Performs a conversion from an to a . /// /// The pointer value. /// @@ -105,6 +121,32 @@ public static CString From(byte* value) return new CString((IntPtr)value); } +#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER + /// + /// Performs an explicit conversion from a to a . + /// + /// The pointer. + /// + /// The resulting . + /// + public static explicit operator CString(ReadOnlySpan value) + { + return new CString(value); + } + + /// + /// Performs a conversion from a to a . + /// + /// The pointer value. + /// + /// The resulting . + /// + public static CString FromReadOnlySpan(ReadOnlySpan value) + { + return new CString(value); + } +#endif + /// /// Performs an implicit conversion from a to a . /// @@ -118,7 +160,7 @@ public static implicit operator IntPtr(CString value) } /// - /// Performs an implicit conversion from a to a . + /// Performs a conversion from a to a . /// /// The pointer. /// From 06e8b1bbef7f8d45ed443f2ad16bea7c0bf010ce Mon Sep 17 00:00:00 2001 From: Lucas Girouard-Stranks <519592+lithiumtoast@users.noreply.github.com> Date: Fri, 3 Jan 2025 13:52:12 -0500 Subject: [PATCH 4/8] Refactor and move files around --- .../GenerateCSharpCode/CodeGenerator.cs | 19 ++++++++++--------- .../CodeGeneratorContext.cs | 7 ++++--- .../Generators/BaseGenerator.cs | 8 ++++---- .../Generators/GeneratorAliasType.cs | 2 +- .../Generators/GeneratorEnum.cs | 2 +- .../Generators/GeneratorFunction.cs | 2 +- .../Generators/GeneratorFunctionPointer.cs | 2 +- .../Generators/GeneratorMacroObject.cs | 4 ++-- .../Generators/GeneratorOpaqueType.cs | 2 +- .../Generators/GeneratorStruct.cs | 2 +- .../c2cs.Tool/GenerateCSharpCode/Startup.cs | 3 ++- .../Assertions/CSharpTestTypeAssertions.cs | 8 -------- .../Extensions/CSharpTestTypeExtensions.cs | 16 ++++++++++++++++ .../Extensions/RoslynExtensions.cs | 2 +- .../c2cs.Tests.Common/Model/CSharpTestEnum.cs | 1 + .../Model/CSharpTestFunction.cs | 1 + .../Model/CSharpTestStructField.cs | 1 + .../Model/CSharpTestStructLayout.cs | 1 + .../c2cs.Tests.Common/Model/CSharpTestType.cs | 1 + .../Functions/function_attributed/Test.cs | 2 ++ .../Functions/function_implicit_enum/Test.cs | 2 ++ .../c2cs.Tests/Functions/function_int/Test.cs | 2 ++ .../Functions/function_int_params_int/Test.cs | 2 ++ .../Test.cs | 2 ++ .../Functions/function_void/Test.cs | 2 ++ 25 files changed, 62 insertions(+), 34 deletions(-) create mode 100644 src/cs/tests/c2cs.Tests.Common/Extensions/CSharpTestTypeExtensions.cs diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGenerator.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGenerator.cs index 1018bb8a..16bc28ec 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGenerator.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGenerator.cs @@ -6,6 +6,7 @@ using System.Collections.Immutable; using System.Linq; using bottlenoselabs.Common.Diagnostics; +using C2CS.GenerateCSharpCode.Generators; using c2ffi.Data; using c2ffi.Data.Nodes; using Microsoft.Extensions.DependencyInjection; @@ -22,7 +23,7 @@ public sealed partial class CodeGenerator private readonly CodeGeneratorDocumentInteropRuntime _codeGeneratorDocumentInteropRuntime; private readonly InputSanitized _input; - private readonly ImmutableDictionary _nodeCodeGenerators; + private readonly ImmutableDictionary _nodeCodeGenerators; public CodeGenerator( IServiceProvider services, @@ -34,15 +35,15 @@ public CodeGenerator( _codeGeneratorDocumentAssemblyAttributes = services.GetRequiredService(); _codeGeneratorDocumentInteropRuntime = services.GetRequiredService(); - _nodeCodeGenerators = new Dictionary + _nodeCodeGenerators = new Dictionary { - { typeof(CEnum), services.GetRequiredService() }, - { typeof(CFunction), services.GetRequiredService() }, - { typeof(CFunctionPointer), services.GetRequiredService() }, - { typeof(CMacroObject), services.GetRequiredService() }, - { typeof(COpaqueType), services.GetRequiredService() }, - { typeof(CRecord), services.GetRequiredService() }, - { typeof(CTypeAlias), services.GetRequiredService() }, + { typeof(CEnum), services.GetRequiredService() }, + { typeof(CFunction), services.GetRequiredService() }, + { typeof(CFunctionPointer), services.GetRequiredService() }, + { typeof(CMacroObject), services.GetRequiredService() }, + { typeof(COpaqueType), services.GetRequiredService() }, + { typeof(CRecord), services.GetRequiredService() }, + { typeof(CTypeAlias), services.GetRequiredService() }, }.ToImmutableDictionary(); } diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorContext.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorContext.cs index 8ddd9dd0..f6b9eb2c 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorContext.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/CodeGeneratorContext.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using bottlenoselabs.Common.Tools; +using C2CS.GenerateCSharpCode.Generators; using c2ffi.Data.Nodes; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -17,7 +18,7 @@ public sealed class CodeGeneratorContext #pragma warning disable IDE0032 private readonly NameMapper _nameMapper; #pragma warning restore IDE0032 - private readonly ImmutableDictionary _nodeCodeGenerators; + private readonly ImmutableDictionary _nodeCodeGenerators; private readonly HashSet _existingNamesCSharp = []; public InputSanitized Input { get; } @@ -26,7 +27,7 @@ public sealed class CodeGeneratorContext public CodeGeneratorContext( InputSanitized input, - ImmutableDictionary nodeCodeGenerators) + ImmutableDictionary nodeCodeGenerators) { Input = input; _nameMapper = new NameMapper(this); @@ -40,7 +41,7 @@ public CodeGeneratorContext( var type = typeof(TNode); if (!_nodeCodeGenerators.TryGetValue(type, out var codeGenerator)) { - throw new ToolException($"A code generator '{nameof(CodeGeneratorNode)}' does not exist for the type '{type.FullName ?? type.Name}'."); + throw new ToolException($"A code generator '{nameof(BaseGenerator)}' does not exist for the type '{type.FullName ?? type.Name}'."); } var nameCSharp = _nameMapper.GetNodeNameCSharp(node); diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/BaseGenerator.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/BaseGenerator.cs index 35e76508..dc677b4f 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/BaseGenerator.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/BaseGenerator.cs @@ -6,9 +6,9 @@ namespace C2CS.GenerateCSharpCode.Generators; -public abstract class CodeGeneratorNode(ILogger logger) +public abstract class BaseGenerator(ILogger logger) { - protected readonly ILogger Logger = logger; + protected readonly ILogger Logger = logger; protected internal abstract string GenerateCode( string nameCSharp, @@ -16,8 +16,8 @@ protected internal abstract string GenerateCode( object obj); } -public abstract class CodeGeneratorNode(ILogger> logger) - : CodeGeneratorNode(logger) +public abstract class BaseGenerator(ILogger> logger) + : BaseGenerator(logger) where TNode : CNode { protected internal override string GenerateCode( diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorAliasType.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorAliasType.cs index 9c4709f8..cb8c4b2e 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorAliasType.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorAliasType.cs @@ -8,7 +8,7 @@ namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public class GeneratorNodeAliasType(ILogger logger) +public class GeneratorAliasType(ILogger logger) : BaseGenerator(logger) { protected override string GenerateCode( diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorEnum.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorEnum.cs index 48a46e89..18a272f1 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorEnum.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorEnum.cs @@ -10,7 +10,7 @@ namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public class GeneratorNodeEnum(ILogger logger) +public class GeneratorEnum(ILogger logger) : BaseGenerator(logger) { protected override string GenerateCode( diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunction.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunction.cs index e586323a..c55dea92 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunction.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunction.cs @@ -12,7 +12,7 @@ namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public class GeneratorNodeFunction(ILogger logger) +public class GeneratorFunction(ILogger logger) : BaseGenerator(logger) { protected override string GenerateCode( diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunctionPointer.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunctionPointer.cs index fd134e66..2adf7915 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunctionPointer.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorFunctionPointer.cs @@ -10,7 +10,7 @@ namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public sealed class GeneratorNodeFunctionPointer(ILogger logger) +public sealed class GeneratorFunctionPointer(ILogger logger) : BaseGenerator(logger) { protected override string GenerateCode( diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorMacroObject.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorMacroObject.cs index ffabcc2c..efb061d7 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorMacroObject.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorMacroObject.cs @@ -8,7 +8,7 @@ namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public class GeneratorNodeMacroObject(ILogger logger) +public class GeneratorMacroObject(ILogger logger) : BaseGenerator(logger) { protected override string GenerateCode( @@ -16,7 +16,7 @@ protected override string GenerateCode( { var cSharpTypeName = context.NameMapper.GetTypeNameCSharp(node.Type); var code = $""" - public static {cSharpTypeName} {nameCSharp} = ({cSharpTypeName}){node.Value}; + public static readonly {cSharpTypeName} {nameCSharp} = ({cSharpTypeName}){node.Value}; """; return code; diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorOpaqueType.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorOpaqueType.cs index c9523dc9..93f744f5 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorOpaqueType.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorOpaqueType.cs @@ -8,7 +8,7 @@ namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public class GeneratorNodeOpaqueType(ILogger logger) +public class GeneratorOpaqueType(ILogger logger) : BaseGenerator(logger) { protected override string GenerateCode( diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorStruct.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorStruct.cs index 376edc25..3155d418 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorStruct.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorStruct.cs @@ -9,7 +9,7 @@ namespace C2CS.GenerateCSharpCode.Generators; [UsedImplicitly] -public class GeneratorNodeStruct(ILogger logger) +public class GeneratorStruct(ILogger logger) : BaseGenerator(logger) { protected override string GenerateCode(string nameCSharp, CodeGeneratorContext context, CRecord record) diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Startup.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Startup.cs index f2468f24..d871980c 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Startup.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Startup.cs @@ -4,6 +4,7 @@ using System.Collections.Immutable; using System.Linq; using System.Reflection; +using C2CS.GenerateCSharpCode.Generators; using Microsoft.Extensions.DependencyInjection; namespace C2CS.GenerateCSharpCode; @@ -26,7 +27,7 @@ public static void ConfigureServices(IServiceCollection services) private static void AddNodeCodeGenerators(IServiceCollection services) { var assembly = Assembly.GetExecutingAssembly(); - var types = assembly.GetTypes().Where(p => !p.IsAbstract && typeof(CodeGeneratorNode).IsAssignableFrom(p)) + var types = assembly.GetTypes().Where(p => !p.IsAbstract && typeof(BaseGenerator).IsAssignableFrom(p)) .ToImmutableArray(); foreach (var type in types) { diff --git a/src/cs/tests/c2cs.Tests.Common/Assertions/CSharpTestTypeAssertions.cs b/src/cs/tests/c2cs.Tests.Common/Assertions/CSharpTestTypeAssertions.cs index d4f1a3ab..124aaacd 100644 --- a/src/cs/tests/c2cs.Tests.Common/Assertions/CSharpTestTypeAssertions.cs +++ b/src/cs/tests/c2cs.Tests.Common/Assertions/CSharpTestTypeAssertions.cs @@ -8,14 +8,6 @@ namespace C2CS.Tests.Common.Assertions; #pragma warning disable SA1649 -public static class CSharpTestTypeExtensions -#pragma warning restore SA1649 -{ - public static CSharpTestTypeAssertions Should(this CSharpTestType? instance) - { - return new(instance); - } -} public class CSharpTestTypeAssertions(CSharpTestType? instance) : ReferenceTypeAssertions(instance) { diff --git a/src/cs/tests/c2cs.Tests.Common/Extensions/CSharpTestTypeExtensions.cs b/src/cs/tests/c2cs.Tests.Common/Extensions/CSharpTestTypeExtensions.cs new file mode 100644 index 00000000..90dde5cb --- /dev/null +++ b/src/cs/tests/c2cs.Tests.Common/Extensions/CSharpTestTypeExtensions.cs @@ -0,0 +1,16 @@ +// Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. +// Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. + +using C2CS.Tests.Common.Assertions; +using C2CS.Tests.Common.Model; + +namespace C2CS.Tests.Common.Extensions; + +public static class CSharpTestTypeExtensions +#pragma warning restore SA1649 +{ + public static CSharpTestTypeAssertions Should(this CSharpTestType? instance) + { + return new(instance); + } +} diff --git a/src/cs/tests/c2cs.Tests.Common/Extensions/RoslynExtensions.cs b/src/cs/tests/c2cs.Tests.Common/Extensions/RoslynExtensions.cs index 664a068f..05bd2673 100644 --- a/src/cs/tests/c2cs.Tests.Common/Extensions/RoslynExtensions.cs +++ b/src/cs/tests/c2cs.Tests.Common/Extensions/RoslynExtensions.cs @@ -4,7 +4,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace C2CS.Tests.Common; +namespace C2CS.Tests.Common.Extensions; public static class RoslynExtensions { diff --git a/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestEnum.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestEnum.cs index d70f669d..29a7da44 100644 --- a/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestEnum.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestEnum.cs @@ -1,6 +1,7 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. +using C2CS.Tests.Common.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; diff --git a/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestFunction.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestFunction.cs index ed6bfad8..ed1d1581 100644 --- a/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestFunction.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestFunction.cs @@ -1,6 +1,7 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. +using C2CS.Tests.Common.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; diff --git a/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructField.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructField.cs index 9d5be359..c2d2dd5f 100644 --- a/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructField.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructField.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. using System.Globalization; +using C2CS.Tests.Common.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace C2CS.Tests.Common.Model; diff --git a/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructLayout.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructLayout.cs index 35fd349d..68195214 100644 --- a/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructLayout.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestStructLayout.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. using System.Globalization; +using C2CS.Tests.Common.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace C2CS.Tests.Common.Model; diff --git a/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestType.cs b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestType.cs index 41d5746d..5e536775 100644 --- a/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestType.cs +++ b/src/cs/tests/c2cs.Tests.Common/Model/CSharpTestType.cs @@ -1,6 +1,7 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. +using C2CS.Tests.Common.Extensions; using Microsoft.CodeAnalysis; namespace C2CS.Tests.Common.Model; diff --git a/src/cs/tests/c2cs.Tests/Functions/function_attributed/Test.cs b/src/cs/tests/c2cs.Tests/Functions/function_attributed/Test.cs index 36900f84..41f4f1c8 100644 --- a/src/cs/tests/c2cs.Tests/Functions/function_attributed/Test.cs +++ b/src/cs/tests/c2cs.Tests/Functions/function_attributed/Test.cs @@ -1,6 +1,8 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. +using C2CS.Tests.Common.Extensions; + namespace C2CS.Tests.Functions.function_attributed; public class Test : WriteCSharpCodeTest diff --git a/src/cs/tests/c2cs.Tests/Functions/function_implicit_enum/Test.cs b/src/cs/tests/c2cs.Tests/Functions/function_implicit_enum/Test.cs index 3e630007..445ff36f 100644 --- a/src/cs/tests/c2cs.Tests/Functions/function_implicit_enum/Test.cs +++ b/src/cs/tests/c2cs.Tests/Functions/function_implicit_enum/Test.cs @@ -1,6 +1,8 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. +using C2CS.Tests.Common.Extensions; + namespace C2CS.Tests.Functions.function_implicit_enum; public class Test : WriteCSharpCodeTest diff --git a/src/cs/tests/c2cs.Tests/Functions/function_int/Test.cs b/src/cs/tests/c2cs.Tests/Functions/function_int/Test.cs index 9329c274..287c92dd 100644 --- a/src/cs/tests/c2cs.Tests/Functions/function_int/Test.cs +++ b/src/cs/tests/c2cs.Tests/Functions/function_int/Test.cs @@ -1,6 +1,8 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. +using C2CS.Tests.Common.Extensions; + namespace C2CS.Tests.Functions.function_int; public class Test : WriteCSharpCodeTest diff --git a/src/cs/tests/c2cs.Tests/Functions/function_int_params_int/Test.cs b/src/cs/tests/c2cs.Tests/Functions/function_int_params_int/Test.cs index 91a8c50c..f76da216 100644 --- a/src/cs/tests/c2cs.Tests/Functions/function_int_params_int/Test.cs +++ b/src/cs/tests/c2cs.Tests/Functions/function_int_params_int/Test.cs @@ -1,6 +1,8 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. +using C2CS.Tests.Common.Extensions; + namespace C2CS.Tests.Functions.function_int_params_int; public class Test : WriteCSharpCodeTest diff --git a/src/cs/tests/c2cs.Tests/Functions/function_uint64_params_uint8_uint16_uint32/Test.cs b/src/cs/tests/c2cs.Tests/Functions/function_uint64_params_uint8_uint16_uint32/Test.cs index 7425e6fa..8171287e 100644 --- a/src/cs/tests/c2cs.Tests/Functions/function_uint64_params_uint8_uint16_uint32/Test.cs +++ b/src/cs/tests/c2cs.Tests/Functions/function_uint64_params_uint8_uint16_uint32/Test.cs @@ -1,6 +1,8 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. +using C2CS.Tests.Common.Extensions; + #pragma warning disable CA1707 namespace C2CS.Tests.Functions.function_uint64_params_uint8_uint16_uint32; diff --git a/src/cs/tests/c2cs.Tests/Functions/function_void/Test.cs b/src/cs/tests/c2cs.Tests/Functions/function_void/Test.cs index 7abb9cb2..8fde30d0 100644 --- a/src/cs/tests/c2cs.Tests/Functions/function_void/Test.cs +++ b/src/cs/tests/c2cs.Tests/Functions/function_void/Test.cs @@ -1,6 +1,8 @@ // Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved. // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. +using C2CS.Tests.Common.Extensions; + namespace C2CS.Tests.Functions.function_void; public class Test : WriteCSharpCodeTest From b4112f1c35edabb193c35a85068b4b64087f9e6a Mon Sep 17 00:00:00 2001 From: Lucas Girouard-Stranks <519592+lithiumtoast@users.noreply.github.com> Date: Fri, 3 Jan 2025 13:52:28 -0500 Subject: [PATCH 5/8] Disable NuGet package for Runtime --- src/cs/production/Interop.Runtime/Interop.Runtime.csproj | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/cs/production/Interop.Runtime/Interop.Runtime.csproj b/src/cs/production/Interop.Runtime/Interop.Runtime.csproj index 4c73af00..c82da143 100644 --- a/src/cs/production/Interop.Runtime/Interop.Runtime.csproj +++ b/src/cs/production/Interop.Runtime/Interop.Runtime.csproj @@ -11,13 +11,7 @@ - true - $(GitRepositoryPath)/nupkg - https://github.com/bottlenoselabs/c2cs - bottlenoselabs.c2cs.Interop.Runtime - C# runtime glue for bindings generated by C2CS. - $(NoWarn);NU5104 - MIT + false From 447ec1e371847cd63c69cef4cdeea3bf546228aa Mon Sep 17 00:00:00 2001 From: Lucas Girouard-Stranks <519592+lithiumtoast@users.noreply.github.com> Date: Fri, 3 Jan 2025 13:52:43 -0500 Subject: [PATCH 6/8] Use .NET 9 when generating code example --- .../helloworld/helloworld-bindgen/config-generate-cs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cs/examples/helloworld/helloworld-bindgen/config-generate-cs.json b/src/cs/examples/helloworld/helloworld-bindgen/config-generate-cs.json index d0af200c..373c5ee2 100644 --- a/src/cs/examples/helloworld/helloworld-bindgen/config-generate-cs.json +++ b/src/cs/examples/helloworld/helloworld-bindgen/config-generate-cs.json @@ -3,5 +3,5 @@ "outputFileDirectory": "./../helloworld-app/Generated", "className": "my_c_library", "namespaceName": "helloworld", - "targetFrameworkMoniker": "net8.0" + "targetFrameworkMoniker": "net9.0" } From 4e47ad85f6d65635d9015f0799fa0cf5a5a8557a Mon Sep 17 00:00:00 2001 From: Lucas Girouard-Stranks <519592+lithiumtoast@users.noreply.github.com> Date: Fri, 3 Jan 2025 14:12:06 -0500 Subject: [PATCH 7/8] Update C# example program --- src/cs/examples/helloworld/helloworld-app/Program.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cs/examples/helloworld/helloworld-app/Program.cs b/src/cs/examples/helloworld/helloworld-app/Program.cs index ce1292e0..cb843502 100644 --- a/src/cs/examples/helloworld/helloworld-app/Program.cs +++ b/src/cs/examples/helloworld/helloworld-app/Program.cs @@ -13,10 +13,12 @@ private static unsafe void Main() { hw_hello_world(); +#if NET7_0_OR_GREATER // NOTE: If you apply the `u8`, it's a UTF-8 string literal and does not allocate the string on the heap! - // See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types#utf-8-string-literals + // Only available in C# 11 (.NET 7+). See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types#utf-8-string-literals var cString1 = (CString)"Hello world from C# using UTF-8 string literal! No need to free this string!"u8; hw_pass_string(cString1); +#endif // NOTE: If you don't apply the `u8` it's a UTF-16 string which needs to be converted to UTF-8 and allocated. // This is done by calling `CString.FromString` or using the explicit CString conversion operator. @@ -38,15 +40,22 @@ private static unsafe void Main() hw_pass_integers_by_reference(&a, &b, &c); #if NET5_0_OR_GREATER + // NOTE: Function pointers provide a more efficient way to execute callbacks from C instead of using delegates. + // A struct will be generated to "house" the function pointer regardless, in this case: `FnPtr_CString_Void`. + // - It uses the same naming as `System.Func<>`. The last type on the name is always the return type. In this case 'void`. + // Only available in C# 9 (.NET 5+). See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/unsafe-code#function-pointers + // Additionally function pointers need to use the `address-of` operator (&) to a C# static function marked with the UnmanagedCallersOnly attribute. See https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.unmanagedcallersonlyattribute?view=net-9.0 var functionPointer = new FnPtr_CString_Void(&Callback); #else var functionPointer = new FnPtr_CString_Void(Callback); #endif + using var cStringCallback = (CString)"Hello from callback!"; hw_invoke_callback(functionPointer, cStringCallback); } #if NET5_0_OR_GREATER + // NOTE: Function pointers need to use the UnmanagedCallersOnly attribute. See https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.unmanagedcallersonlyattribute?view=net-9.0 [UnmanagedCallersOnly] #endif private static void Callback(CString param) From 3677012a6dc45932f0b0ee3d44b510371642af52 Mon Sep 17 00:00:00 2001 From: Lucas Girouard-Stranks <519592+lithiumtoast@users.noreply.github.com> Date: Fri, 3 Jan 2025 14:29:25 -0500 Subject: [PATCH 8/8] Add support for macro objects being UTF-8 string literals --- .../Generated/AssemblyAttributes.g.cs | 4 ++-- .../helloworld-app/Generated/Runtime.g.cs | 2 +- .../helloworld-app/Generated/my_c_library.g.cs | 4 +++- .../examples/helloworld/helloworld-app/Program.cs | 3 +++ .../my_c_library/include/my_c_library.h | 2 ++ .../Generators/GeneratorMacroObject.cs | 15 ++++++++++++++- 6 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/cs/examples/helloworld/helloworld-app/Generated/AssemblyAttributes.g.cs b/src/cs/examples/helloworld/helloworld-app/Generated/AssemblyAttributes.g.cs index 04f7b5de..95945a4e 100644 --- a/src/cs/examples/helloworld/helloworld-app/Generated/AssemblyAttributes.g.cs +++ b/src/cs/examples/helloworld/helloworld-app/Generated/AssemblyAttributes.g.cs @@ -1,6 +1,6 @@ // -// This code was generated by the following tool on 2025-01-03 12:59:48 GMT-05:00: -// https://github.com/bottlenoselabs/c2cs (v2025-01-03 12:59:48 GMT-05:00) +// This code was generated by the following tool on 2025-01-03 14:27:37 GMT-05:00: +// https://github.com/bottlenoselabs/c2cs (v2025-01-03 14:27:37 GMT-05:00) // // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. // diff --git a/src/cs/examples/helloworld/helloworld-app/Generated/Runtime.g.cs b/src/cs/examples/helloworld/helloworld-app/Generated/Runtime.g.cs index 850727db..29d549d2 100644 --- a/src/cs/examples/helloworld/helloworld-app/Generated/Runtime.g.cs +++ b/src/cs/examples/helloworld/helloworld-app/Generated/Runtime.g.cs @@ -1,5 +1,5 @@ // -// This code was generated by the following tool on 2025-01-03 12:59:48 GMT-05:00: +// This code was generated by the following tool on 2025-01-03 14:27:37 GMT-05:00: // https://github.com/bottlenoselabs/c2cs (v0.0.0.0) // // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. diff --git a/src/cs/examples/helloworld/helloworld-app/Generated/my_c_library.g.cs b/src/cs/examples/helloworld/helloworld-app/Generated/my_c_library.g.cs index 3c3b65ce..520eb7d5 100644 --- a/src/cs/examples/helloworld/helloworld-app/Generated/my_c_library.g.cs +++ b/src/cs/examples/helloworld/helloworld-app/Generated/my_c_library.g.cs @@ -1,5 +1,5 @@ // -// This code was generated by the following tool on 2025-01-03 12:59:48 GMT-05:00: +// This code was generated by the following tool on 2025-01-03 14:27:37 GMT-05:00: // https://github.com/bottlenoselabs/c2cs (v0.0.0.0) // // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. @@ -49,6 +49,8 @@ public static unsafe partial class my_c_library [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })] public static partial void hw_pass_string(CString s); + public static readonly CString HW_STRING_POINTER = (CString)"Hello world using UTF-8 string literal from the C library's data segment!"u8; + public enum hw_my_enum_week_day : int { HW_MY_ENUM_WEEK_DAY_UNKNOWN = 0, diff --git a/src/cs/examples/helloworld/helloworld-app/Program.cs b/src/cs/examples/helloworld/helloworld-app/Program.cs index cb843502..c8b40a05 100644 --- a/src/cs/examples/helloworld/helloworld-app/Program.cs +++ b/src/cs/examples/helloworld/helloworld-app/Program.cs @@ -18,6 +18,9 @@ private static unsafe void Main() // Only available in C# 11 (.NET 7+). See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types#utf-8-string-literals var cString1 = (CString)"Hello world from C# using UTF-8 string literal! No need to free this string!"u8; hw_pass_string(cString1); + + // NOTE: This is particularly useful if you have C defines to strings which are stored in the data segment of the loaded C library. + hw_pass_string(HW_STRING_POINTER); #endif // NOTE: If you don't apply the `u8` it's a UTF-16 string which needs to be converted to UTF-8 and allocated. diff --git a/src/cs/examples/helloworld/helloworld-bindgen/my_c_library/include/my_c_library.h b/src/cs/examples/helloworld/helloworld-bindgen/my_c_library/include/my_c_library.h index caca0a14..52675bf2 100644 --- a/src/cs/examples/helloworld/helloworld-bindgen/my_c_library/include/my_c_library.h +++ b/src/cs/examples/helloworld/helloworld-bindgen/my_c_library/include/my_c_library.h @@ -12,6 +12,8 @@ #define MY_C_LIBRARY_API_DECL extern __attribute__ ((visibility("default"))) #endif +#define HW_STRING_POINTER "Hello world using UTF-8 string literal from the C library's data segment!" + typedef enum hw_my_enum_week_day { HW_MY_ENUM_WEEK_DAY_UNKNOWN, HW_MY_ENUM_WEEK_DAY_MONDAY, diff --git a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorMacroObject.cs b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorMacroObject.cs index efb061d7..cf139b59 100644 --- a/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorMacroObject.cs +++ b/src/cs/production/c2cs.Tool/GenerateCSharpCode/Generators/GeneratorMacroObject.cs @@ -15,9 +15,22 @@ protected override string GenerateCode( string nameCSharp, CodeGeneratorContext context, CMacroObject node) { var cSharpTypeName = context.NameMapper.GetTypeNameCSharp(node.Type); - var code = $""" + + string code; +#pragma warning disable IDE0045 + if (cSharpTypeName == "CString" && node.Value.StartsWith('"') && node.Value.EndsWith('"')) +#pragma warning restore IDE0045 + { + code = $""" + public static readonly {cSharpTypeName} {nameCSharp} = ({cSharpTypeName}){node.Value}u8; + """; + } + else + { + code = $""" public static readonly {cSharpTypeName} {nameCSharp} = ({cSharpTypeName}){node.Value}; """; + } return code; }