Skip to content
This repository was archived by the owner on Mar 30, 2019. It is now read-only.

Commit 1ab7aa9

Browse files
rockhymasJerry Lin
authored andcommitted
Fully populate derived structs
Structs, such as DWrite's FontMetrics1, derive from other structs. Ensure that these structs contain fields from their ancestor structs since C# does not have struct inheritance.
1 parent 5e9be87 commit 1ab7aa9

3 files changed

Lines changed: 79 additions & 38 deletions

File tree

Source/Tools/SharpGen/CppModel/CppStruct.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ public class CppStruct : CppElement
3535
[XmlAttribute("align")]
3636
public int Align { get; set; }
3737

38+
/// <summary>
39+
/// Gets or sets the name of the parent.
40+
/// </summary>
41+
/// <value>The name of the parent.</value>
42+
[XmlAttribute("base")]
43+
public string ParentName { get; set; }
44+
3845
/// <summary>
3946
/// Gets the fields.
4047
/// </summary>

Source/Tools/SharpGen/Generator/StructTransform.cs

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -94,53 +94,65 @@ private void Process(CsStruct csStruct)
9494
if (csStruct.IsFullyMapped)
9595
return;
9696

97-
// Set IsFullyMappy in order to avoid recursive mapping
98-
csStruct.IsFullyMapped = true;
97+
// Set IsFullyMappy in order to avoid recursive mapping
98+
csStruct.IsFullyMapped = true;
9999

100-
// Get the associated CppStruct and CSharpTag
101-
var cppStruct = (CppStruct)csStruct.CppElement;
102-
bool hasMarshalType = csStruct.HasMarshalType;
100+
// Get the associated CppStruct and CSharpTag
101+
var cppStruct = (CppStruct)csStruct.CppElement;
102+
bool hasMarshalType = csStruct.HasMarshalType;
103103

104-
// If this structure need to me moved to another container, move it now
105-
foreach (var keyValuePair in _mapMoveStructToInner)
104+
// If this structure need to me moved to another container, move it now
105+
foreach (var keyValuePair in _mapMoveStructToInner)
106+
{
107+
if (keyValuePair.Key.Match(csStruct.CppElementName).Success)
106108
{
107-
if (keyValuePair.Key.Match(csStruct.CppElementName).Success)
108-
{
109-
string cppName = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value);
110-
var destSharpStruct = (CsStruct)Manager.FindBindType(cppName);
111-
// Remove the struct from his container
112-
csStruct.Parent.Remove(csStruct);
113-
// Add this struct to the new container struct
114-
destSharpStruct.Add(csStruct);
115-
}
109+
string cppName = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value);
110+
var destSharpStruct = (CsStruct)Manager.FindBindType(cppName);
111+
// Remove the struct from his container
112+
csStruct.Parent.Remove(csStruct);
113+
// Add this struct to the new container struct
114+
destSharpStruct.Add(csStruct);
116115
}
116+
}
117+
118+
// Current offset of a field
119+
int currentFieldAbsoluteOffset = 0;
117120

118-
// Current offset of a field
119-
int currentFieldAbsoluteOffset = 0;
121+
// Last field offset
122+
int previousFieldOffsetIndex = -1;
120123

121-
int fieldCount = cppStruct.IsEmpty ? 0 : cppStruct.Items.Count;
124+
// Size of the last field
125+
int previousFieldSize = 0;
122126

127+
//
128+
int maxSizeOfField = 0;
123129

124-
// Last field offset
125-
int previousFieldOffsetIndex = -1;
130+
bool isInUnion = false;
126131

127-
// Size of the last field
128-
int previousFieldSize = 0;
132+
int cumulatedBitOffset = 0;
129133

130-
//
131-
int maxSizeOfField = 0;
132134

133-
bool isInUnion = false;
135+
var inheritedStructs = new Stack<CppStruct>();
136+
var currentStruct = cppStruct;
137+
while (currentStruct != null && currentStruct.ParentName != currentStruct.Name)
138+
{
139+
inheritedStructs.Push(currentStruct);
140+
currentStruct = Manager.FindBindType(currentStruct.ParentName)?.CppElement as CppStruct;
141+
}
134142

135-
int cumulatedBitOffset = 0;
143+
while (inheritedStructs.Count > 0)
144+
{
145+
currentStruct = inheritedStructs.Pop();
146+
147+
int fieldCount = currentStruct.IsEmpty ? 0 : currentStruct.Items.Count;
136148

137149
// -------------------------------------------------------------------------------
138150
// Iterate on all fields and perform mapping
139151
// -------------------------------------------------------------------------------
140152
for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++)
141153
{
142-
var cppField = (CppField) cppStruct.Items[fieldIndex];
143-
Logger.RunInContext(cppField.ToString(), () =>
154+
var cppField = (CppField)currentStruct.Items[fieldIndex];
155+
Logger.RunInContext(cppField.ToString(), () =>
144156
{
145157
var fieldStruct = Manager.GetCsType<CsField>(cppField, true);
146158
csStruct.Add(fieldStruct);
@@ -196,9 +208,9 @@ private void Process(CsStruct csStruct)
196208

197209
var nextFieldIndex = fieldIndex + 1;
198210
if ((previousFieldOffsetIndex == cppField.Offset)
199-
|| (nextFieldIndex < fieldCount && ((CppField)cppStruct.Items[nextFieldIndex]).Offset == cppField.Offset))
211+
|| (nextFieldIndex < fieldCount && ((CppField)currentStruct.Items[nextFieldIndex]).Offset == cppField.Offset))
200212
{
201-
if(previousFieldOffsetIndex != cppField.Offset)
213+
if (previousFieldOffsetIndex != cppField.Offset)
202214
{
203215
maxSizeOfField = 0;
204216
}
@@ -214,10 +226,11 @@ private void Process(CsStruct csStruct)
214226
previousFieldOffsetIndex = cppField.Offset;
215227
});
216228
}
229+
}
217230

218231
// In case of explicit layout, check that we can safely generate it on both x86 and x64 (in case of an union
219232
// using pointers, we can't)
220-
if(csStruct.ExplicitLayout)
233+
if (csStruct.ExplicitLayout)
221234
{
222235
var fieldList = csStruct.Fields.ToList();
223236
for(int i = 0; i < fieldList.Count; i++)

Source/Tools/SharpGen/Parser/CppParser.cs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -866,9 +866,9 @@ private CppInterface ParseInterface(XElement xElement)
866866
var cppInterface = xElement.Annotation<CppInterface>();
867867
if (cppInterface != null)
868868
return cppInterface;
869-
869+
870870
// Else, create a new CppInterface
871-
cppInterface = new CppInterface() { Name = xElement.AttributeValue("name") };
871+
cppInterface = new CppInterface() { Name = xElement.AttributeValue("name") };
872872
xElement.AddAnnotation(cppInterface);
873873

874874
// Enter Interface description
@@ -1007,18 +1007,23 @@ private CppField ParseField(XElement xElement)
10071007
/// <returns>A C++ struct parsed</returns>
10081008
private CppStruct ParseStructOrUnion(XElement xElement, CppElement cppParent = null, int innerAnonymousIndex = 0)
10091009
{
1010+
var cppStruct = xElement.Annotation<CppStruct>();
1011+
if (cppStruct != null)
1012+
return cppStruct;
1013+
10101014
// Build struct name directly from the struct name or based on the parent
10111015
var structName = xElement.AttributeValue("name") ?? "";
10121016
if (cppParent != null)
10131017
{
1014-
if (string.IsNullOrEmpty(structName))
1018+
if (string.IsNullOrEmpty(structName))
10151019
structName = cppParent.Name + "_INNER_" + innerAnonymousIndex;
10161020
else
10171021
structName = cppParent.Name + "_" + structName + "_INNER";
10181022
}
10191023

10201024
// Create struct
1021-
var cppStruct = new CppStruct { Name = structName };
1025+
cppStruct = new CppStruct { Name = structName };
1026+
xElement.AddAnnotation(cppStruct);
10221027
bool isUnion = (xElement.Name.LocalName == CastXml.TagUnion);
10231028

10241029
// Get align from structure
@@ -1034,6 +1039,22 @@ private CppStruct ParseStructOrUnion(XElement xElement, CppElement cppParent = n
10341039
// Enter struct/union description
10351040
Logger.PushContext("{0}:[{1}]", xElement.Name.LocalName, cppStruct.Name);
10361041

1042+
var basesValue = xElement.AttributeValue("bases");
1043+
var bases = basesValue != null ? basesValue.Split(' ') : Enumerable.Empty<string>();
1044+
foreach (var xElementBaseId in bases)
1045+
{
1046+
if (string.IsNullOrEmpty(xElementBaseId))
1047+
continue;
1048+
1049+
var xElementBase = _mapIdToXElement[xElementBaseId];
1050+
1051+
CppStruct cppStructBase = null;
1052+
Logger.RunInContext("Base", () => { cppStructBase = ParseStructOrUnion(xElementBase); });
1053+
1054+
if (string.IsNullOrEmpty(cppStructBase.ParentName))
1055+
cppStruct.ParentName = cppStructBase.Name;
1056+
}
1057+
10371058
// Parse all fields
10381059
int fieldOffset = 0;
10391060
int innerStructCount = 0;
@@ -1077,7 +1098,7 @@ private CppStruct ParseStructOrUnion(XElement xElement, CppElement cppParent = n
10771098
// Get the type name from the inner-struct and set it to the field
10781099
cppField.TypeName = fieldSubStruct.Name;
10791100
_currentCppInclude.Add(fieldSubStruct);
1080-
}
1101+
}
10811102
}
10821103

10831104
// Go to next field offset if not in union
@@ -1465,7 +1486,7 @@ private static string ConvertFundamentalType(string typeName)
14651486
default:
14661487
Logger.Error("Unhandled partial type [{0}] from Fundamental type [{1}]", type, typeName);
14671488
break;
1468-
}
1489+
}
14691490
}
14701491

14711492
if (longCount == 1 && outputType == "double")

0 commit comments

Comments
 (0)