Skip to content

Commit 5552f2b

Browse files
committed
Generate valid C# for pure functions returning or taking dependent pointers
Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent caaf89d commit 5552f2b

File tree

5 files changed

+82
-4
lines changed

5 files changed

+82
-4
lines changed

src/Generator/Generators/CSharp/CSharpSources.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,7 +1676,7 @@ public void GenerateVTable(Class @class)
16761676
NewLine();
16771677

16781678
// Generate a delegate type for each method.
1679-
foreach (var method in wrappedEntries.Select(e => e.Method))
1679+
foreach (var method in wrappedEntries.Select(e => e.Method).Where(m => !m.Ignore))
16801680
GenerateVTableMethodDelegates(containingClass, method.Namespace.IsDependent ?
16811681
(Method) method.InstantiatedFrom : method);
16821682

@@ -1701,16 +1701,19 @@ public void GenerateVTable(Class @class)
17011701
WriteLine($"static VTableLoader()");
17021702
{
17031703
WriteOpenBraceAndIndent();
1704-
foreach (var entry in wrappedEntries.Distinct())
1704+
foreach (var entry in wrappedEntries.Distinct().Where(e => !e.Method.Ignore))
17051705
{
17061706
var name = GetVTableMethodDelegateName(entry.Method);
17071707
WriteLine($"{name + "Instance"} += {name}Hook;");
17081708
}
17091709
for (var i = 0; i < wrappedEntries.Count; ++i)
17101710
{
17111711
var entry = wrappedEntries[i];
1712-
var name = GetVTableMethodDelegateName(entry.Method);
1713-
WriteLine($"Thunks[{i}] = Marshal.GetFunctionPointerForDelegate({name + "Instance"});");
1712+
if (!entry.Method.Ignore)
1713+
{
1714+
var name = GetVTableMethodDelegateName(entry.Method);
1715+
WriteLine($"Thunks[{i}] = Marshal.GetFunctionPointerForDelegate({name + "Instance"});");
1716+
}
17141717
}
17151718
UnindentAndWriteCloseBrace();
17161719
}

src/Generator/Passes/GenerateAbstractImplementationsPass.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Collections.Generic;
22
using System.Linq;
33
using CppSharp.AST;
4+
using CppSharp.AST.Extensions;
45

56
namespace CppSharp.Passes
67
{
@@ -72,6 +73,12 @@ public override bool VisitClassDecl(Class @class)
7273
};
7374
impl.OverriddenMethods.Clear();
7475
impl.OverriddenMethods.Add(abstractMethod);
76+
if (abstractMethod.OriginalReturnType.Type.IsDependentPointer() ||
77+
abstractMethod.Parameters.Any(p => p.Type.IsDependentPointer()))
78+
{
79+
// this is an extension but marks the class as an abstract impl
80+
impl.ExplicitlyIgnore();
81+
}
7582
internalImpl.Methods.Add(impl);
7683
}
7784

src/Generator/Passes/SpecializationMethodsWithDependentPointersPass.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ private static Method GetExtensionMethodForDependentPointer(Method specializedMe
118118
extensionMethod.OriginalFunction = specializedMethod;
119119
extensionMethod.Kind = CXXMethodKind.Normal;
120120
extensionMethod.IsStatic = true;
121+
if (extensionMethod.IsPure)
122+
{
123+
extensionMethod.IsPure = false;
124+
extensionMethod.SynthKind = FunctionSynthKind.AbstractImplCall;
125+
}
121126

122127
var qualReturnType = extensionMethod.OriginalReturnType;
123128
RemoveTemplateSubstitution(ref qualReturnType);

tests/CSharp/CSharp.Tests.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,6 +1328,18 @@ public void TestAbstractTemplate()
13281328
}
13291329
}
13301330

1331+
[Test]
1332+
public void TestAbstractImplTemplate()
1333+
{
1334+
using (var returnsPointer = new DependentValueFields<int>())
1335+
{
1336+
using (var value = returnsPointer.AbstractReturnPointer)
1337+
{
1338+
Assert.That(new IntPtr(value.AbstractReturnPointer()), Is.EqualTo(IntPtr.Zero));
1339+
}
1340+
}
1341+
}
1342+
13311343
[Test]
13321344
public void TestSpecializationForSecondaryBase()
13331345
{

tests/CSharp/CSharpTemplates.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,50 @@ class DLL_API Ignored
3636
{
3737
};
3838

39+
template <typename T>
40+
class HasAbstractReturnPointer
41+
{
42+
public:
43+
HasAbstractReturnPointer();
44+
~HasAbstractReturnPointer();
45+
virtual const T* abstractReturnPointer() = 0;
46+
};
47+
48+
template <typename T>
49+
HasAbstractReturnPointer<T>::HasAbstractReturnPointer()
50+
{
51+
}
52+
53+
template <typename T>
54+
HasAbstractReturnPointer<T>::~HasAbstractReturnPointer()
55+
{
56+
}
57+
58+
template <typename T>
59+
class ImplReturnPointer : public HasAbstractReturnPointer<T>
60+
{
61+
public:
62+
ImplReturnPointer();
63+
~ImplReturnPointer();
64+
virtual const T* abstractReturnPointer() override;
65+
};
66+
67+
template <typename T>
68+
ImplReturnPointer<T>::ImplReturnPointer()
69+
{
70+
}
71+
72+
template <typename T>
73+
ImplReturnPointer<T>::~ImplReturnPointer()
74+
{
75+
}
76+
77+
template <typename T>
78+
const T* ImplReturnPointer<T>::abstractReturnPointer()
79+
{
80+
return 0;
81+
}
82+
3983
template <typename T>
4084
class IndependentFields : public T1
4185
{
@@ -176,6 +220,7 @@ class DependentValueFields : public Base<T>
176220
const T* returnTakeDependentPointer(const T* p);
177221
const T* propertyReturnDependentPointer();
178222
void hasDefaultDependentParam(T* ptr, const T& refT = T());
223+
HasAbstractReturnPointer<T>* getAbstractReturnPointer();
179224
typedef void (*DependentFunctionPointer)(T);
180225
DependentFunctionPointer dependentFunctionPointerField;
181226
private:
@@ -235,6 +280,12 @@ void DependentValueFields<T>::hasDefaultDependentParam(T* ptr, const T& refT)
235280
{
236281
}
237282

283+
template <typename T>
284+
HasAbstractReturnPointer<T>* DependentValueFields<T>::getAbstractReturnPointer()
285+
{
286+
return new ImplReturnPointer<T>();
287+
}
288+
238289
template <typename T>
239290
DependentValueFields<T>& DependentValueFields<T>::returnInjectedClass()
240291
{

0 commit comments

Comments
 (0)