Skip to content

Commit ae60be4

Browse files
Merge pull request #344 from Berrysoft/dev/varargs
Add support for varargs.
2 parents 851adb8 + 329e6fc commit ae60be4

12 files changed

Lines changed: 95 additions & 3 deletions

File tree

sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -592,8 +592,11 @@ public void BeginParameter(in ParameterDesc info)
592592
_customAttrIsForParameter = false;
593593

594594
Write(info.Type);
595-
Write(' ');
596-
Write(info.Name);
595+
if (info.Name.Length > 0)
596+
{
597+
Write(' ');
598+
Write(info.Name);
599+
}
597600
}
598601
}
599602

sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,9 @@ private void VisitFunctionDecl(FunctionDecl functionDecl)
597597

598598
_outputBuilder.BeginFunctionInnerPrototype(in desc);
599599

600-
if (isVirtual || (isCxxMethodDecl && !hasBody && cxxMethodDecl.IsInstance))
600+
bool needsThis = isVirtual || (isCxxMethodDecl && !hasBody && cxxMethodDecl.IsInstance);
601+
602+
if (needsThis)
601603
{
602604
Debug.Assert(cxxRecordDecl != null);
603605

@@ -636,6 +638,21 @@ private void VisitFunctionDecl(FunctionDecl functionDecl)
636638

637639
Visit(functionDecl.Parameters);
638640

641+
if (functionDecl.IsVariadic)
642+
{
643+
if (needsThis || functionDecl.Parameters.Any())
644+
{
645+
_outputBuilder.WriteParameterSeparator();
646+
}
647+
var parameterDesc = new ParameterDesc
648+
{
649+
Name = "",
650+
Type = "__arglist"
651+
};
652+
_outputBuilder.BeginParameter(in parameterDesc);
653+
_outputBuilder.EndParameter(in parameterDesc);
654+
}
655+
639656
_outputBuilder.EndFunctionInnerPrototype(in desc);
640657

641658
if (hasBody && !isVirtual)
@@ -674,6 +691,15 @@ private void VisitFunctionDecl(FunctionDecl functionDecl)
674691
}
675692
}
676693

694+
if (functionDecl.IsVariadic)
695+
{
696+
if (parameters.Count != 0)
697+
{
698+
outputBuilder.Write(", ");
699+
}
700+
outputBuilder.Write("__arglist");
701+
}
702+
677703
outputBuilder.Write(')');
678704

679705
outputBuilder.NeedsSemicolon = true;

sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,6 +1932,14 @@ private Type[] GetBitfieldCount(RecordDecl recordDecl)
19321932

19331933
private CallingConvention GetCallingConvention(Cursor cursor, Cursor context, Type type)
19341934
{
1935+
if (cursor is FunctionDecl functionDecl)
1936+
{
1937+
if (functionDecl.IsVariadic)
1938+
{
1939+
return CallingConvention.Cdecl;
1940+
}
1941+
}
1942+
19351943
if (cursor is NamedDecl namedDecl)
19361944
{
19371945
if (TryGetRemappedValue(namedDecl, _config.WithCallConvs, out var callConv, matchStar: true))

tests/ClangSharp.PInvokeGenerator.UnitTests/Base/FunctionDeclarationDllImportTest.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ public abstract class FunctionDeclarationDllImportTest : PInvokeGeneratorTest
7373
[Test]
7474
public Task SourceLocationTest() => SourceLocationTestImpl();
7575

76+
[Test]
77+
public Task VarargsTest() => VarargsTestImpl();
78+
7679
protected abstract Task BasicTestImpl();
7780

7881
protected abstract Task ArrayParameterTestImpl();
@@ -106,5 +109,7 @@ public abstract class FunctionDeclarationDllImportTest : PInvokeGeneratorTest
106109
protected abstract Task WithSetLastErrorStarTestImpl();
107110

108111
protected abstract Task SourceLocationTestImpl();
112+
113+
protected abstract Task VarargsTestImpl();
109114
}
110115
}

tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/FunctionDeclarationDllImportTest.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,5 +396,7 @@ public static partial class Methods
396396

397397
return ValidateGeneratedCSharpCompatibleUnixBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute);
398398
}
399+
400+
protected override Task VarargsTestImpl() => Task.CompletedTask;
399401
}
400402
}

tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/FunctionDeclarationDllImportTest.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,5 +395,24 @@ public static partial class Methods
395395

396396
return ValidateGeneratedCSharpCompatibleWindowsBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute);
397397
}
398+
399+
protected override Task VarargsTestImpl()
400+
{
401+
const string InputContents = @"extern ""C"" void MyFunction(int value, ...);";
402+
403+
const string ExpectedOutputContents = @"using System.Runtime.InteropServices;
404+
405+
namespace ClangSharp.Test
406+
{
407+
public static partial class Methods
408+
{
409+
[DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
410+
public static extern void MyFunction(int value, __arglist);
411+
}
412+
}
413+
";
414+
415+
return ValidateGeneratedCSharpCompatibleWindowsBindingsAsync(InputContents, ExpectedOutputContents);
416+
}
398417
}
399418
}

tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/FunctionDeclarationDllImportTest.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,5 +394,7 @@ public static partial class Methods
394394

395395
return ValidateGeneratedCSharpLatestUnixBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute);
396396
}
397+
398+
protected override Task VarargsTestImpl() => Task.CompletedTask;
397399
}
398400
}

tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/FunctionDeclarationDllImportTest.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,5 +394,24 @@ public static partial class Methods
394394

395395
return ValidateGeneratedCSharpLatestWindowsBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute);
396396
}
397+
398+
protected override Task VarargsTestImpl()
399+
{
400+
const string InputContents = @"extern ""C"" void MyFunction(int value, ...);";
401+
402+
const string ExpectedOutputContents = @"using System.Runtime.InteropServices;
403+
404+
namespace ClangSharp.Test
405+
{
406+
public static partial class Methods
407+
{
408+
[DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
409+
public static extern void MyFunction(int value, __arglist);
410+
}
411+
}
412+
";
413+
414+
return ValidateGeneratedCSharpLatestWindowsBindingsAsync(InputContents, ExpectedOutputContents);
415+
}
397416
}
398417
}

tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/FunctionDeclarationDllImportTest.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,5 +447,7 @@ protected override Task SourceLocationTestImpl()
447447

448448
return ValidateGeneratedXmlCompatibleUnixBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute);
449449
}
450+
451+
protected override Task VarargsTestImpl() => Task.CompletedTask;
450452
}
451453
}

tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/FunctionDeclarationDllImportTest.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,5 +447,7 @@ protected override Task SourceLocationTestImpl()
447447

448448
return ValidateGeneratedXmlCompatibleWindowsBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute);
449449
}
450+
451+
protected override Task VarargsTestImpl() => Task.CompletedTask;
450452
}
451453
}

0 commit comments

Comments
 (0)