diff --git a/GroupedNativeMethodsGenerator/Class1.cs b/GroupedNativeMethodsGenerator/Class1.cs
deleted file mode 100644
index 3e15bb0..0000000
--- a/GroupedNativeMethodsGenerator/Class1.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-
-namespace GroupedNativeMethodsGenerator;
-
-[Generator(LanguageNames.CSharp)]
-public partial class GroupedNativeMethodsGenerator : IIncrementalGenerator
-{
- public void Initialize(IncrementalGeneratorInitializationContext context)
- {
- context.RegisterPostInitializationOutput(ctx =>
- {
- ctx.AddSource("GroupedNativeMethodsGenerator.Attribute.cs", """
-namespace GroupedNativeMethodsGenerator
-{
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
- internal sealed class GroupedNativeMethodsAttribute : Attribute
- {
- public string RemovePrefix { get; set; } = "";
- public bool RemoveUntilTypeName { get; set; } = true;
-
- /// Fix method name as C# Style, e.g.: foo_bar_baz() -> FooBarBaz()
- public bool FixMethodName { get; set; } = true;
- }
-}
-""");
- });
-
- var source = context.SyntaxProvider.ForAttributeWithMetadataName("GroupedNativeMethodsGenerator.GroupedNativeMethodsAttribute",
- (node, token) => node is ClassDeclarationSyntax,
- (ctx, token) => ctx);
-
- context.RegisterSourceOutput(source, Emit);
- }
-
- static void Emit(SourceProductionContext context, GeneratorAttributeSyntaxContext source)
- {
- var typeSymbol = (INamedTypeSymbol)source.TargetSymbol;
- var typeNode = (TypeDeclarationSyntax)source.TargetNode;
-
- var ns = typeSymbol.ContainingNamespace.IsGlobalNamespace
- ? ""
- : $"namespace {typeSymbol.ContainingNamespace};";
-
- var fullType = typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)
- .Replace("global::", "")
- .Replace("<", "_")
- .Replace(">", "_");
-
- var methods = typeSymbol.GetMembers()
- .OfType();
-
-
-
- // context.AddSource($"{fullType}.SampleGenerator.g.cs", code);
- }
-}
-
-// TODO:...
-public static class DiagnosticDescriptors
-{
- const string Category = "SampleGenerator";
-
- public static readonly DiagnosticDescriptor ExistsOverrideToString = new(
- id: "SAMPLE001",
- title: "ToString override",
- messageFormat: "The GenerateToString class '{0}' has ToString override but it is not allowed.",
- category: Category,
- defaultSeverity: DiagnosticSeverity.Error,
- isEnabledByDefault: true);
-}
\ No newline at end of file
diff --git a/GroupedNativeMethodsGenerator/GroupedNativeMethodsGenerator.cs b/GroupedNativeMethodsGenerator/GroupedNativeMethodsGenerator.cs
new file mode 100644
index 0000000..b2b2bd4
--- /dev/null
+++ b/GroupedNativeMethodsGenerator/GroupedNativeMethodsGenerator.cs
@@ -0,0 +1,168 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace GroupedNativeMethodsGenerator;
+
+[Generator(LanguageNames.CSharp)]
+public partial class GroupedNativeMethodsGenerator : IIncrementalGenerator
+{
+ public void Initialize(IncrementalGeneratorInitializationContext context)
+ {
+ context.RegisterPostInitializationOutput(ctx =>
+ {
+ ctx.AddSource("GroupedNativeMethodsGenerator.Attribute.cs", """
+namespace GroupedNativeMethodsGenerator
+{
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
+ internal sealed class GroupedNativeMethodsAttribute : Attribute
+ {
+ public string RemovePrefix { get; }
+ public string RemoveSuffix { get; }
+ public bool RemoveUntilTypeName { get; }
+ public bool FixMethodName { get; }
+
+ public GroupedNativeMethodsAttribute(string removePrefix = "", string removeSuffix = "", bool removeUntilTypeName = true, bool fixMethodName = true)
+ {
+ this.RemovePrefix = removePrefix;
+ this.RemoveSuffix = removeSuffix;
+ this.RemoveUntilTypeName = removeUntilTypeName;
+ this.FixMethodName = fixMethodName;
+ }
+ }
+}
+""");
+ });
+
+ var source = context.SyntaxProvider.ForAttributeWithMetadataName("GroupedNativeMethodsGenerator.GroupedNativeMethodsAttribute",
+ (node, token) => node is ClassDeclarationSyntax,
+ (ctx, token) => ctx);
+
+ context.RegisterSourceOutput(source, Emit);
+ }
+
+ static void Emit(SourceProductionContext context, GeneratorAttributeSyntaxContext source)
+ {
+ var typeSymbol = (INamedTypeSymbol)source.TargetSymbol;
+ var typeNode = (TypeDeclarationSyntax)source.TargetNode;
+
+ var ns = typeSymbol.ContainingNamespace.IsGlobalNamespace
+ ? ""
+ : $"namespace {typeSymbol.ContainingNamespace}\n{{";
+
+ var accessibility = typeSymbol.DeclaredAccessibility == Accessibility.Public ? "public" : "internal";
+
+ var fullType = typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)
+ .Replace("global::", "")
+ .Replace("<", "_")
+ .Replace(">", "_");
+
+ var grouped = typeSymbol.GetMembers().OfType()
+ .Where(x => x.Parameters.Length != 0)
+ .Where(x => x.Parameters[0].Type is IPointerTypeSymbol t && (t.PointedAtType.SpecialType is SpecialType.None) && t.PointedAtType.TypeKind != TypeKind.Pointer)
+ .ToLookup(x =>
+ {
+ return ((IPointerTypeSymbol)x.Parameters[0].Type).PointedAtType.ToDisplayString();
+ });
+
+ var libTypeName = typeSymbol.Name;
+ var removePrefix = (string)source.Attributes[0].ConstructorArguments[0].Value!;
+ var removeSuffix = (string)source.Attributes[0].ConstructorArguments[1].Value!;
+ var removeUntilTypeName = (bool)source.Attributes[0].ConstructorArguments[2].Value!;
+ var fixMethodName = (bool)source.Attributes[0].ConstructorArguments[3].Value!;
+
+ var code = new StringBuilder();
+
+ code.AppendLine($$"""
+//
+#nullable enable
+#pragma warning disable CS8600
+#pragma warning disable CS8601
+#pragma warning disable CS8602
+#pragma warning disable CS8603
+#pragma warning disable CS8604
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+{{ns}}
+
+ {{accessibility}} static unsafe class {{typeSymbol.Name}}GroupingExtensions
+ {
+""");
+ foreach (var g in grouped)
+ {
+ code.AppendLine($"#region {g.Key}({g.Count()})");
+ code.AppendLine();
+ foreach (var item in g)
+ {
+ var firstArgument = item.Parameters[0];
+ var ret = item.ReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+ var requireRet = ret == "void" ? "" : "return ";
+
+ var convertedMethodName = ConvertMethodName(((IPointerTypeSymbol)firstArgument.Type).PointedAtType.Name, item.Name, removePrefix, removeSuffix, removeUntilTypeName, fixMethodName);
+ var pointedType = ((IPointerTypeSymbol)firstArgument.Type).PointedAtType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+ var parameterPairs = string.Join("", item.Parameters.Skip(1).Select(x => $", {x.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)} @{x.Name}"));
+ var parameterNames = string.Join("", item.Parameters.Skip(1).Select(x => $", @{x.Name}"));
+
+ code.AppendLine($" public static {ret} {convertedMethodName}(this ref {pointedType} @{firstArgument.Name}{parameterPairs})");
+ code.AppendLine(" {");
+ code.AppendLine($" {requireRet}{libTypeName}.{item.Name}(({pointedType}*)Unsafe.AsPointer(ref @{firstArgument.Name}){parameterNames});");
+ code.AppendLine(" }");
+ code.AppendLine("");
+ }
+ code.AppendLine($"#endregion");
+ code.AppendLine();
+ }
+
+ code.AppendLine(" }");
+ if (ns != "")
+ {
+ code.AppendLine("}");
+ }
+
+ context.AddSource($"{fullType}.GroupedNativeMethods.g.cs", code.ToString());
+ }
+
+ static string ConvertMethodName(string typeName, string methodName, string removePrefix, string removeSuffix, bool removeUntilTypeName, bool fixMethodName)
+ {
+ if (removeUntilTypeName)
+ {
+ var match = methodName.IndexOf(typeName);
+ if (match != -1)
+ {
+ methodName = methodName.Substring(match + typeName.Length);
+ goto FINAL;
+ }
+ }
+
+ if (!string.IsNullOrEmpty(removePrefix))
+ {
+ methodName = Regex.Replace(methodName, $"^{Regex.Escape(removePrefix)}", "");
+ }
+
+ FINAL:
+
+ if (!string.IsNullOrEmpty(removeSuffix))
+ {
+ methodName = Regex.Replace(methodName, $"{Regex.Escape(removeSuffix)}$", "");
+ }
+
+ methodName = methodName.Trim('_');
+
+ if (fixMethodName)
+ {
+ var split = methodName.Split('_');
+ methodName = string.Concat(split.Select(x =>
+ {
+ if (x.Length == 0) return x;
+ if (x.Length == 1) return char.ToUpper(x[0]).ToString();
+ return char.ToUpper(x[0]) + x.Substring(1);
+ }));
+ }
+
+ return methodName;
+ }
+}
\ No newline at end of file
diff --git a/csbindgen/src/emitter.rs b/csbindgen/src/emitter.rs
index 0a82213..9f68467 100644
--- a/csbindgen/src/emitter.rs
+++ b/csbindgen/src/emitter.rs
@@ -292,6 +292,7 @@ pub fn emit_csharp(
// This code is generated by csbindgen.
// DON'T CHANGE THIS DIRECTLY.
//
+#pragma warning disable CS8500
#pragma warning disable CS8981
using System;
using System.Runtime.InteropServices;
diff --git a/dotnet-sandbox/BindingGroupExtensions.cs b/dotnet-sandbox/BindingGroupExtensions.cs
index 1aeb8f3..09c500c 100644
--- a/dotnet-sandbox/BindingGroupExtensions.cs
+++ b/dotnet-sandbox/BindingGroupExtensions.cs
@@ -1,50 +1,44 @@
-using CsBindgen;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading.Tasks;
+
-namespace CsbindgenDotnetConsoleApp
+namespace Physx
{
- // Concept for grouping extension
-
- internal static unsafe class BindingGroupExtensions
+ [GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "Px")]
+ internal static unsafe partial class LibPhysxd
{
- // public static extern bool quiche_conn_set_keylog_path(quiche_conn* conn, byte* path);
- // public static extern nuint quiche_conn_max_send_udp_payload_size(quiche_conn* conn);
- // public static extern int quiche_conn_close(quiche_conn* conn, [MarshalAs(UnmanagedType.U1)] bool app, ulong err, byte* reason, nuint reason_len);
+ }
+}
- public static bool SetKeylogPath(this ref quiche_conn conn, byte* path)
- {
- return LibQuiche.quiche_conn_set_keylog_path((quiche_conn*)Unsafe.AsPointer(ref conn), path);
- }
+namespace CsBindgen
+{
+ [GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "b3")]
+ internal static unsafe partial class LibBullet3
+ {
+ }
- public static nuint MaxSendUdpPayloadSize(this ref quiche_conn conn)
- {
- return LibQuiche.quiche_conn_max_send_udp_payload_size((quiche_conn*)Unsafe.AsPointer(ref conn));
- }
-
- public static int MaxSendUdpPayloadSize(this ref quiche_conn conn, bool app, ulong err, byte* reason, nuint reason_len)
- {
- return LibQuiche.quiche_conn_close((quiche_conn*)Unsafe.AsPointer(ref conn), app, err, reason, reason_len);
- }
-
- public static bool Hoge(quiche_conn* conn, byte* path)
- {
- return conn->SetKeylogPath(path);
- }
+ [GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "quiche_")]
+ internal static unsafe partial class LibQuiche
+ {
+ }
+ [GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "sqlite3_")]
+ public static unsafe partial class LibSqlite3
+ {
}
}
-namespace Physx
+namespace PixivApi.ImageFile
{
- [GroupedNativeMethodsGenerator.GroupedNativeMethods]
- internal static unsafe partial class LibPhysxd
+ [GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "png_")]
+ internal static unsafe partial class LibPng16
+ {
+ }
+}
+
+namespace Jolt
+{
+ [GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "JPH_")]
+ internal static unsafe partial class NativeMethods
{
}
}
\ No newline at end of file
diff --git a/dotnet-sandbox/CsbindgenDotnetConsoleApp.sln b/dotnet-sandbox/CsbindgenDotnetConsoleApp.sln
deleted file mode 100644
index e01f71d..0000000
--- a/dotnet-sandbox/CsbindgenDotnetConsoleApp.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.5.33414.496
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CsbindgenDotnetConsoleApp", "CsbindgenDotnetConsoleApp.csproj", "{3ED7C644-A880-426C-9BF1-24675D7A6299}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {3ED7C644-A880-426C-9BF1-24675D7A6299}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {3ED7C644-A880-426C-9BF1-24675D7A6299}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {3ED7C644-A880-426C-9BF1-24675D7A6299}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {3ED7C644-A880-426C-9BF1-24675D7A6299}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {DD647440-C307-4A09-9D97-DEA74660F797}
- EndGlobalSection
-EndGlobal
diff --git a/dotnet-sandbox/NativeMethods.cs b/dotnet-sandbox/NativeMethods.cs
index 3be320d..c6362c5 100644
--- a/dotnet-sandbox/NativeMethods.cs
+++ b/dotnet-sandbox/NativeMethods.cs
@@ -2,6 +2,7 @@
// This code is generated by csbindgen.
// DON'T CHANGE THIS DIRECTLY.
//
+#pragma warning disable CS8500
#pragma warning disable CS8981
using System;
using System.Runtime.InteropServices;
diff --git a/dotnet-sandbox/libphysx_csbindgen.cs b/dotnet-sandbox/libphysx_csbindgen.cs
index bd4fb67..5a1c68e 100644
--- a/dotnet-sandbox/libphysx_csbindgen.cs
+++ b/dotnet-sandbox/libphysx_csbindgen.cs
@@ -2,6 +2,7 @@
// This code is generated by csbindgen.
// DON'T CHANGE THIS DIRECTLY.
//
+#pragma warning disable CS8500
#pragma warning disable CS8981
using System;
using System.Runtime.InteropServices;
diff --git a/dotnet-sandbox/libpng16_csbindgen.cs b/dotnet-sandbox/libpng16_csbindgen.cs
index 3beb0d7..2858808 100644
--- a/dotnet-sandbox/libpng16_csbindgen.cs
+++ b/dotnet-sandbox/libpng16_csbindgen.cs
@@ -2,6 +2,7 @@
// This code is generated by csbindgen.
// DON'T CHANGE THIS DIRECTLY.
//
+#pragma warning disable CS8500
#pragma warning disable CS8981
using System;
using System.Runtime.InteropServices;
diff --git a/dotnet-sandbox/lz4_bindgen.cs b/dotnet-sandbox/lz4_bindgen.cs
index a44812e..3954733 100644
--- a/dotnet-sandbox/lz4_bindgen.cs
+++ b/dotnet-sandbox/lz4_bindgen.cs
@@ -2,6 +2,7 @@
// This code is generated by csbindgen.
// DON'T CHANGE THIS DIRECTLY.
//
+#pragma warning disable CS8500
#pragma warning disable CS8981
using System;
using System.Runtime.InteropServices;