Exemple #1
0
        /// <summary>
        /// Maps the C++ struct to C# struct.
        /// </summary>
        /// <param name="csStruct">The c sharp struct.</param>
        private void Process(CsStruct csStruct)
        {
            // TODO: this mapping must be robust. Current caculation for field offset is not always accurate for union.
            // TODO: need to handle align/packing correctly.

            // If a struct was already mapped, then return immediatly
            // The method MapStruct can be called recursivelly
            if (csStruct.IsFullyMapped)
                return;

                // 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;

                // If this structure need to me moved to anoter container, move it now
                foreach (var keyValuePair in _mapMoveStructToInner)
                {
                    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);
                    }
                }

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

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


                // Offset stored for each field
                int[] offsetOfFields = new int[fieldCount];

                // Last field offset
                int lastCppFieldOffset = -1;

                // Size of the last field
                int lastFieldSize = 0;

                // 
                int maxSizeOfField = 0;

                bool isInUnion = false;

                int cumulatedBitOffset = 0;

                // -------------------------------------------------------------------------------
                // 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 fieldStruct = Manager.GetCsType<CsField>(cppField, true);

                        // Get name
                        fieldStruct.Name = NamingRules.Rename(cppField);

                        // BoolToInt doesn't generate native Marshaling although they have a different marshaller
                        if (!fieldStruct.IsBoolToInt && fieldStruct.HasMarshalType)
                            hasMarshalType = true;

                        // If last field has same offset, then it's a union
                        // CurrentOffset is not moved
                        if (isInUnion && lastCppFieldOffset != cppField.Offset)
                        {
                            lastFieldSize = maxSizeOfField;
                            maxSizeOfField = 0;
                            isInUnion = false;
                        }

                        currentOffset += lastFieldSize;
                        offsetOfFields[cppField.Offset] = currentOffset;
                        // Get correct offset (for handling union)
                        fieldStruct.Offset = offsetOfFields[cppField.Offset];
                        fieldStruct.IsBitField = cppField.IsBitField;

                        // Handle bit fields : calculate BitOffset and BitMask for this field
                        if (lastCppFieldOffset != cppField.Offset)
                        {
                            cumulatedBitOffset = 0;
                        }
                        if (cppField.IsBitField)
                        {
                            int lastCumulatedBitOffset = cumulatedBitOffset;
                            cumulatedBitOffset += cppField.BitOffset;
                            fieldStruct.BitMask = ((1 << cppField.BitOffset) - 1); // &~((1 << (lastCumulatedBitOffset + 1)) - 1);
                            //fieldStruct.BitMask2 = ((1 << cppField.BitOffset) - 1); // &~((1 << (lastCumulatedBitOffset + 1)) - 1);
                            fieldStruct.BitOffset = lastCumulatedBitOffset;
                        }
                        csStruct.Add(fieldStruct);
                        // TODO : handle packing rules here!!!!!

                        // If last field has same offset, then it's a union
                        // CurrentOffset is not moved
                        if (lastCppFieldOffset == cppField.Offset ||
                            ((fieldIndex + 1) < fieldCount &&
                             (cppStruct.Items[fieldIndex + 1] as CppField).Offset == cppField.Offset))
                        {
                            isInUnion = true;
                            csStruct.ExplicitLayout = true;
                            maxSizeOfField = fieldStruct.SizeOf > maxSizeOfField ? fieldStruct.SizeOf : maxSizeOfField;
                            lastFieldSize = 0;
                        }
                        else
                        {
                            lastFieldSize = fieldStruct.SizeOf;
                        }
                        lastCppFieldOffset = cppField.Offset;

                    });
                }
            csStruct.SizeOf = currentOffset + lastFieldSize;
            csStruct.HasMarshalType = hasMarshalType;
        }
        /// <summary>
        /// Maps the C++ struct to C# struct.
        /// </summary>
        /// <param name="csStruct">The c sharp struct.</param>
        private void Process(CsStruct csStruct)
        {
            // TODO: this mapping must be robust. Current calculation for field offset is not always accurate for union.
            // TODO: need to handle align/packing correctly.

            // If a struct was already mapped, then return immediately
            // The method MapStruct can be called recursively
            if (csStruct.IsFullyMapped)
                return;

                // 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;

                // 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)
                    {
                        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;

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


                // Last field offset
                int previousFieldOffsetIndex = -1;

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

                // 
                int maxSizeOfField = 0;

                bool isInUnion = false;

                int cumulatedBitOffset = 0;

                // -------------------------------------------------------------------------------
                // 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 fieldStruct = Manager.GetCsType<CsField>(cppField, true);
                        csStruct.Add(fieldStruct);

                        // Get name
                        fieldStruct.Name = NamingRules.Rename(cppField);

                        // BoolToInt doesn't generate native Marshaling although they have a different marshaller
                        if (!fieldStruct.IsBoolToInt && fieldStruct.HasMarshalType)
                            hasMarshalType = true;


                        // If last field has same offset, then it's a union
                        // CurrentOffset is not moved
                        if (isInUnion && previousFieldOffsetIndex != cppField.Offset)
                        {
                            previousFieldSize = maxSizeOfField;
                            maxSizeOfField = 0;
                            isInUnion = false;
                        }

                        currentFieldAbsoluteOffset += previousFieldSize;
                        var fieldAlignment = (fieldStruct.MarshalType ?? fieldStruct.PublicType).CalculateAlignment();

                        // If field alignment is < 0, then we have a pointer somewhere so we can't align
                        if (fieldAlignment > 0)
                        {
                            // otherwise, align the field on the alignment requirement of the field
                            int delta = (currentFieldAbsoluteOffset % fieldAlignment);
                            if (delta != 0)
                            {
                                currentFieldAbsoluteOffset += fieldAlignment - delta;
                            }
                        }

                        // Get correct offset (for handling union)
                        fieldStruct.Offset = currentFieldAbsoluteOffset;
                        fieldStruct.IsBitField = cppField.IsBitField;

                        // Handle bit fields : calculate BitOffset and BitMask for this field
                        if (previousFieldOffsetIndex != cppField.Offset)
                        {
                            cumulatedBitOffset = 0;
                        }
                        if (cppField.IsBitField)
                        {
                            int lastCumulatedBitOffset = cumulatedBitOffset;
                            cumulatedBitOffset += cppField.BitOffset;
                            fieldStruct.BitMask = ((1 << cppField.BitOffset) - 1); // &~((1 << (lastCumulatedBitOffset + 1)) - 1);
                            fieldStruct.BitOffset = lastCumulatedBitOffset;
                        }


                        var nextFieldIndex = fieldIndex + 1;
                        if ((previousFieldOffsetIndex == cppField.Offset)
                           || (nextFieldIndex < fieldCount && ((CppField)cppStruct.Items[nextFieldIndex]).Offset == cppField.Offset))
                        {
                            if(previousFieldOffsetIndex != cppField.Offset)
                            {
                                maxSizeOfField = 0;
                            }
                            maxSizeOfField = fieldStruct.SizeOf > maxSizeOfField ? fieldStruct.SizeOf : maxSizeOfField;
                            isInUnion = true;
                            csStruct.ExplicitLayout = true;
                            previousFieldSize = 0;
                        }
                        else
                        {
                            previousFieldSize = fieldStruct.SizeOf;
                        }
                        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)
            {
                var fieldList = csStruct.Fields.ToList();
                for(int i = 0; i < fieldList.Count; i++)
                {
                    var field = fieldList[i];
                    var fieldAlignment = (field.MarshalType ?? field.PublicType).CalculateAlignment();

                    if(fieldAlignment < 0)
                    {
                        // If pointer field is not the last one, than we can't handle it
                        if ((i + 1) < fieldList.Count)
                        {
                            Logger.Error(
                                "The field [{0}] in structure [{1}] has pointer alignment within a structure that contains an union. An explicit layout cannot be handled on both x86/x64. This structure needs manual layout (remove fields from definition) and write them manually in xml mapping files",
                                field.CppElementName,
                                csStruct.CppElementName);
                            break;
                        }
                    }
                }
            }

            csStruct.SizeOf = currentFieldAbsoluteOffset + previousFieldSize;
            csStruct.HasMarshalType = hasMarshalType;
        }