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

Commit

Permalink
Fully populate derived structs
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rockhymas authored and Jerry Lin committed May 17, 2017
1 parent 5e9be87 commit 1ab7aa9
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 38 deletions.
7 changes: 7 additions & 0 deletions Source/Tools/SharpGen/CppModel/CppStruct.cs
Expand Up @@ -35,6 +35,13 @@ public class CppStruct : CppElement
[XmlAttribute("align")]
public int Align { get; set; }

/// <summary>
/// Gets or sets the name of the parent.
/// </summary>
/// <value>The name of the parent.</value>
[XmlAttribute("base")]
public string ParentName { get; set; }

/// <summary>
/// Gets the fields.
/// </summary>
Expand Down
77 changes: 45 additions & 32 deletions Source/Tools/SharpGen/Generator/StructTransform.cs
Expand Up @@ -94,53 +94,65 @@ private void Process(CsStruct csStruct)
if (csStruct.IsFullyMapped)
return;

// Set IsFullyMappy in order to avoid recursive mapping
csStruct.IsFullyMapped = true;
// Set IsFullyMappy in order to avoid recursive mapping
csStruct.IsFullyMapped = true;

// Get the associated CppStruct and CSharpTag
var cppStruct = (CppStruct)csStruct.CppElement;
bool hasMarshalType = csStruct.HasMarshalType;
// Get the associated CppStruct and CSharpTag
var cppStruct = (CppStruct)csStruct.CppElement;
bool hasMarshalType = csStruct.HasMarshalType;

// If this structure need to me moved to another container, move it now
foreach (var keyValuePair in _mapMoveStructToInner)
// If this structure need to me moved to another container, move it now
foreach (var keyValuePair in _mapMoveStructToInner)
{
if (keyValuePair.Key.Match(csStruct.CppElementName).Success)
{
if (keyValuePair.Key.Match(csStruct.CppElementName).Success)
{
string cppName = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value);
var destSharpStruct = (CsStruct)Manager.FindBindType(cppName);
// Remove the struct from his container
csStruct.Parent.Remove(csStruct);
// Add this struct to the new container struct
destSharpStruct.Add(csStruct);
}
string cppName = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value);
var destSharpStruct = (CsStruct)Manager.FindBindType(cppName);
// Remove the struct from his container
csStruct.Parent.Remove(csStruct);
// Add this struct to the new container struct
destSharpStruct.Add(csStruct);
}
}

// Current offset of a field
int currentFieldAbsoluteOffset = 0;

// Current offset of a field
int currentFieldAbsoluteOffset = 0;
// Last field offset
int previousFieldOffsetIndex = -1;

int fieldCount = cppStruct.IsEmpty ? 0 : cppStruct.Items.Count;
// Size of the last field
int previousFieldSize = 0;

//
int maxSizeOfField = 0;

// Last field offset
int previousFieldOffsetIndex = -1;
bool isInUnion = false;

// Size of the last field
int previousFieldSize = 0;
int cumulatedBitOffset = 0;

//
int maxSizeOfField = 0;

bool isInUnion = false;
var inheritedStructs = new Stack<CppStruct>();
var currentStruct = cppStruct;
while (currentStruct != null && currentStruct.ParentName != currentStruct.Name)
{
inheritedStructs.Push(currentStruct);
currentStruct = Manager.FindBindType(currentStruct.ParentName)?.CppElement as CppStruct;
}

int cumulatedBitOffset = 0;
while (inheritedStructs.Count > 0)
{
currentStruct = inheritedStructs.Pop();

int fieldCount = currentStruct.IsEmpty ? 0 : currentStruct.Items.Count;

// -------------------------------------------------------------------------------
// Iterate on all fields and perform mapping
// -------------------------------------------------------------------------------
for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++)
{
var cppField = (CppField) cppStruct.Items[fieldIndex];
Logger.RunInContext(cppField.ToString(), () =>
var cppField = (CppField)currentStruct.Items[fieldIndex];
Logger.RunInContext(cppField.ToString(), () =>
{
var fieldStruct = Manager.GetCsType<CsField>(cppField, true);
csStruct.Add(fieldStruct);
Expand Down Expand Up @@ -196,9 +208,9 @@ private void Process(CsStruct csStruct)
var nextFieldIndex = fieldIndex + 1;
if ((previousFieldOffsetIndex == cppField.Offset)
|| (nextFieldIndex < fieldCount && ((CppField)cppStruct.Items[nextFieldIndex]).Offset == cppField.Offset))
|| (nextFieldIndex < fieldCount && ((CppField)currentStruct.Items[nextFieldIndex]).Offset == cppField.Offset))
{
if(previousFieldOffsetIndex != cppField.Offset)
if (previousFieldOffsetIndex != cppField.Offset)
{
maxSizeOfField = 0;
}
Expand All @@ -214,10 +226,11 @@ private void Process(CsStruct csStruct)
previousFieldOffsetIndex = cppField.Offset;
});
}
}

// In case of explicit layout, check that we can safely generate it on both x86 and x64 (in case of an union
// using pointers, we can't)
if(csStruct.ExplicitLayout)
if (csStruct.ExplicitLayout)
{
var fieldList = csStruct.Fields.ToList();
for(int i = 0; i < fieldList.Count; i++)
Expand Down
33 changes: 27 additions & 6 deletions Source/Tools/SharpGen/Parser/CppParser.cs
Expand Up @@ -866,9 +866,9 @@ private CppInterface ParseInterface(XElement xElement)
var cppInterface = xElement.Annotation<CppInterface>();
if (cppInterface != null)
return cppInterface;

// Else, create a new CppInterface
cppInterface = new CppInterface() { Name = xElement.AttributeValue("name") };
cppInterface = new CppInterface() { Name = xElement.AttributeValue("name") };
xElement.AddAnnotation(cppInterface);

// Enter Interface description
Expand Down Expand Up @@ -1007,18 +1007,23 @@ private CppField ParseField(XElement xElement)
/// <returns>A C++ struct parsed</returns>
private CppStruct ParseStructOrUnion(XElement xElement, CppElement cppParent = null, int innerAnonymousIndex = 0)
{
var cppStruct = xElement.Annotation<CppStruct>();
if (cppStruct != null)
return cppStruct;

// Build struct name directly from the struct name or based on the parent
var structName = xElement.AttributeValue("name") ?? "";
if (cppParent != null)
{
if (string.IsNullOrEmpty(structName))
if (string.IsNullOrEmpty(structName))
structName = cppParent.Name + "_INNER_" + innerAnonymousIndex;
else
structName = cppParent.Name + "_" + structName + "_INNER";
}

// Create struct
var cppStruct = new CppStruct { Name = structName };
cppStruct = new CppStruct { Name = structName };
xElement.AddAnnotation(cppStruct);
bool isUnion = (xElement.Name.LocalName == CastXml.TagUnion);

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

var basesValue = xElement.AttributeValue("bases");
var bases = basesValue != null ? basesValue.Split(' ') : Enumerable.Empty<string>();
foreach (var xElementBaseId in bases)
{
if (string.IsNullOrEmpty(xElementBaseId))
continue;

var xElementBase = _mapIdToXElement[xElementBaseId];

CppStruct cppStructBase = null;
Logger.RunInContext("Base", () => { cppStructBase = ParseStructOrUnion(xElementBase); });

if (string.IsNullOrEmpty(cppStructBase.ParentName))
cppStruct.ParentName = cppStructBase.Name;
}

// Parse all fields
int fieldOffset = 0;
int innerStructCount = 0;
Expand Down Expand Up @@ -1077,7 +1098,7 @@ private CppStruct ParseStructOrUnion(XElement xElement, CppElement cppParent = n
// Get the type name from the inner-struct and set it to the field
cppField.TypeName = fieldSubStruct.Name;
_currentCppInclude.Add(fieldSubStruct);
}
}
}

// Go to next field offset if not in union
Expand Down Expand Up @@ -1465,7 +1486,7 @@ private static string ConvertFundamentalType(string typeName)
default:
Logger.Error("Unhandled partial type [{0}] from Fundamental type [{1}]", type, typeName);
break;
}
}
}

if (longCount == 1 && outputType == "double")
Expand Down

0 comments on commit 1ab7aa9

Please sign in to comment.