private MemberDeclarationSyntax GenerateBackingField(CsField field, CsTypeBase backingType, bool isArray = false, bool propertyBacking = true, bool document = false) { var elementType = ParseTypeName(backingType.QualifiedName); var fieldDecl = FieldDeclaration( VariableDeclaration( isArray ? ArrayType(elementType, SingletonList(ArrayRankSpecifier())) : elementType, SingletonSeparatedList( VariableDeclarator(propertyBacking ? field.IntermediateMarshalName : field.Name) ) ) ) .WithModifiers( propertyBacking ? TokenList(Token(SyntaxKind.InternalKeyword)) : field.VisibilityTokenList ); if (explicitLayout) { fieldDecl = AddFieldOffsetAttribute(fieldDecl, field.Offset); } return(document ? AddDocumentationTrivia(fieldDecl, field) : fieldDecl); }
private static MemberDeclarationSyntax GenerateBackingField(CsField field, CsTypeBase backingType, int?offset, bool isArray = false, bool propertyBacking = true, SyntaxTrivia?docTrivia = null) { var elementType = ParseTypeName(backingType.QualifiedName); var fieldDecl = FieldDeclaration( VariableDeclaration( isArray ? ArrayType(elementType, SingletonList(ArrayRankSpecifier())) : elementType, SingletonSeparatedList( VariableDeclarator(propertyBacking ? field.IntermediateMarshalName : field.Name) ) ) ) .WithModifiers( propertyBacking ? TokenList(Token(SyntaxKind.InternalKeyword)) : field.VisibilityTokenList ); if (offset.HasValue) { fieldDecl = fieldDecl.WithAttributeLists(SingletonList( AttributeList( SingletonSeparatedList(Attribute( ParseName("System.Runtime.InteropServices.FieldOffset"), AttributeArgumentList( SingletonSeparatedList(AttributeArgument( LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(offset.Value)))))))) )); } return(docTrivia is { } trivia?fieldDecl.WithLeadingTrivia(trivia) : fieldDecl); }
private void CreateCore(CsMarshalBase csMarshallable) { var marshallable = (CppMarshallable)csMarshallable.CppElement; CsTypeBase publicType = null; CsTypeBase marshalType = null; var mappingRule = marshallable.Rule; var publicTypeName = mappingRule is { MappingType : { } mapType } ? mapType : marshallable.TypeName;
public override void Init(TransformManager manager, Logger logger) { base.Init(manager, logger); DefaultInterfaceCppObject = new CsInterface { Name = manager.GlobalNamespace.GetTypeName("CppObject") }; DefaultCallbackable = new CsInterface { Name = manager.GlobalNamespace.GetTypeName("ICallbackable") }; DefaultComObjectCallback = new CsInterface { Name = manager.GlobalNamespace.GetTypeName("ComObjectCallback") }; }
public static string GetNativeImplementationQualifiedName(this CsTypeBase type) => type is CsInterface iface?iface.GetNativeImplementationOrThis().QualifiedName : type.QualifiedName;
private void ProcessDefines(ConfigFile file) { foreach (var defineRule in file.Extension.OfType <DefineExtensionRule>()) { CsTypeBase defineType = null; if (defineRule.Enum != null) { var newEnum = new CsEnum { Name = defineRule.Enum, UnderlyingType = !string.IsNullOrWhiteSpace(defineRule.UnderlyingType) ? (CsFundamentalType)typeRegistry.ImportType(defineRule.UnderlyingType) : null }; defineType = newEnum; if (defineRule.SizeOf.HasValue && newEnum.UnderlyingType == null) { var size = defineRule.SizeOf.Value; switch (size) { case 1: newEnum.UnderlyingType = typeRegistry.ImportType(typeof(byte)); break; case 2: newEnum.UnderlyingType = typeRegistry.ImportType(typeof(short)); break; case 4: newEnum.UnderlyingType = typeRegistry.ImportType(typeof(int)); break; default: break; } } } else if (defineRule.Struct != null) { var newStruct = new CsStruct { Name = defineRule.Struct }; defineType = newStruct; if (defineRule.HasCustomMarshal.HasValue) { newStruct.HasMarshalType = defineRule.HasCustomMarshal.Value; } if (defineRule.IsStaticMarshal.HasValue) { newStruct.IsStaticMarshal = defineRule.IsStaticMarshal.Value; } if (defineRule.HasCustomNew.HasValue) { newStruct.HasCustomNew = defineRule.HasCustomNew.Value; } if (defineRule.SizeOf.HasValue) { newStruct.SetSize(defineRule.SizeOf.Value); } if (defineRule.Align.HasValue) { newStruct.Align = defineRule.Align.Value; } } else if (defineRule.Interface != null) { var iface = new CsInterface { Name = defineRule.Interface, ShadowName = defineRule.ShadowName, VtblName = defineRule.VtblName }; if (defineRule.NativeImplementation != null) { iface.NativeImplementation = new CsInterface { Name = defineRule.NativeImplementation, IsDualCallback = true }; iface.IsCallback = true; iface.IsDualCallback = true; typeRegistry.DefineType(iface.NativeImplementation); } defineType = iface; } else { Logger.Error(LoggingCodes.MissingElementInRule, "Invalid rule [{0}]. Requires one of enum, struct, or interface", defineRule); continue; } // Define this type typeRegistry.DefineType(defineType); } }
public CsExpressionConstant(CppElement cppElement, string name, CsTypeBase type, string value) : base(cppElement, name) { Type = type ?? throw new ArgumentNullException(nameof(type)); Value = value ?? throw new ArgumentNullException(nameof(value)); }
public BoundType(CsTypeBase csType, CsTypeBase?marshalType, string?source) { CSharpType = csType ?? throw new ArgumentNullException(nameof(csType)); MarshalType = marshalType; Source = source; }
/// <summary> /// Gets the C# type from a C++ type. /// </summary> /// <typeparam name="T">The C# type to return</typeparam> /// <param name="marshallable">The marshallable element to create the C# type from.</param> /// <returns>An instantiated C# type</returns> private T CreateCore <T>(CppMarshallable marshallable) where T : CsMarshalBase, new() { CsTypeBase publicType = null; CsTypeBase marshalType = null; var csMarshallable = new T { CppElement = marshallable, IsArray = marshallable.IsArray, HasPointer = !string.IsNullOrEmpty(marshallable.Pointer) && (marshallable.Pointer.Contains("*") || marshallable.Pointer.Contains("&")), }; // TODO: handle multidimensional arrays // Calculate ArrayDimension int arrayDimensionValue = 0; if (marshallable.IsArray) { if (string.IsNullOrEmpty(marshallable.ArrayDimension)) { arrayDimensionValue = 0; } else if (!int.TryParse(marshallable.ArrayDimension, out arrayDimensionValue)) { arrayDimensionValue = 1; } } // If array Dimension is 0, then it is not an array if (arrayDimensionValue == 0) { marshallable.IsArray = false; csMarshallable.IsArray = false; } csMarshallable.ArrayDimensionValue = arrayDimensionValue; string publicTypeName = marshallable.GetTypeNameWithMapping(); switch (publicTypeName) { case "char": publicType = typeRegistry.ImportType(typeof(byte)); if (csMarshallable.HasPointer) { publicType = typeRegistry.ImportType(typeof(string)); } if (csMarshallable.IsArray) { publicType = typeRegistry.ImportType(typeof(string)); marshalType = typeRegistry.ImportType(typeof(byte)); } break; case "wchar_t": publicType = typeRegistry.ImportType(typeof(char)); csMarshallable.IsWideChar = true; if (csMarshallable.HasPointer) { publicType = typeRegistry.ImportType(typeof(string)); } if (csMarshallable.IsArray) { publicType = typeRegistry.ImportType(typeof(string)); marshalType = typeRegistry.ImportType(typeof(char)); } break; default: // If CppType is an array, try first to get the binding for this array if (marshallable.IsArray) { publicType = typeRegistry.FindBoundType(publicTypeName + "[" + marshallable.ArrayDimension + "]"); } // Else get the typeName if (publicType == null) { // Try to get a declared type // If it fails, then this type is unknown publicType = typeRegistry.FindBoundType(publicTypeName); if (publicType == null) { logger.Fatal("Unknown type found [{0}]", publicTypeName); } } else { csMarshallable.ArrayDimensionValue = 0; csMarshallable.IsArray = false; } // By default, use the underlying native type as the marshal type // if it differs from the public type. marshalType = typeRegistry.FindBoundType(marshallable.TypeName); if (publicType == marshalType) { marshalType = null; } if (marshalType == null) { // Otherwise, get the registered marshal type if one exists marshalType = typeRegistry.FindBoundMarshalType(publicTypeName); } if (publicType is CsStruct csStruct) { // If a structure was not already parsed, then parse it before going further if (!csStruct.IsFullyMapped) { RequestStructProcessing?.Invoke(csStruct); } if (!csStruct.IsFullyMapped) // No one tried to map the struct so we can't continue. { logger.Fatal($"No struct processor processed {csStruct.QualifiedName}. Cannot continue processing"); } // If referenced structure has a specialized marshalling, then use the structure's built-in marshalling if (csStruct.HasMarshalType && !csMarshallable.HasPointer) { marshalType = publicType; } } else if (publicType is CsEnum referenceEnum) { marshalType = null; // enums don't need a marshal type. They can always marshal as their underlying type. } break; } // Set bool to int conversion case csMarshallable.IsBoolToInt = marshalType is CsFundamentalType marshalFundamental && IsIntegerFundamentalType(marshalFundamental) && publicType is CsFundamentalType publicFundamental && publicFundamental.Type == typeof(bool); if (publicType.QualifiedName == globalNamespace.GetTypeName(WellKnownName.PointerSize)) { marshalType = typeRegistry.ImportType(typeof(IntPtr)); } // Present void* elements as IntPtr. Marshal strings as IntPtr if (csMarshallable.HasPointer) { if (publicTypeName == "void") { publicType = typeRegistry.ImportType(typeof(IntPtr)); marshalType = typeRegistry.ImportType(typeof(IntPtr)); } else if (publicType == typeRegistry.ImportType(typeof(string))) { marshalType = typeRegistry.ImportType(typeof(IntPtr)); } } csMarshallable.PublicType = publicType; csMarshallable.MarshalType = marshalType ?? publicType; csMarshallable.Relations = RelationParser.ParseRelation(marshallable.GetMappingRule().Relation, logger); return(csMarshallable); }
private static void DuplicateMethodSpecial(CsInterface interfaceType, CsMethod csMethod, CsTypeBase intPtrType) { bool hasComArrayLike = false; foreach (var csParameter in csMethod.Parameters) { if (csParameter.IsInComArrayLike) { hasComArrayLike = true; break; } } // Look for at least one parameter ComArray candidate if (hasComArrayLike) { // Create a new method and transforms all array of ComObject to ComArray<ComObject> var newMethod = (CsMethod)csMethod.Clone(); foreach (var csSubParameter in newMethod.Parameters) { if (csSubParameter.IsInComArrayLike) { csSubParameter.PublicType = new CsComArray((CsInterface)csSubParameter.PublicType); } } interfaceType.Add(newMethod); } if (hasComArrayLike || csMethod.RequestRawPtr) { // Create private method with raw pointers for arrays, with all arrays as pure IntPtr // In order to be able to generate method taking single element var rawMethod = (CsMethod)csMethod.Clone(); rawMethod.Visibility = Visibility.Private; foreach (var csSubParameter in rawMethod.Parameters) { if (csSubParameter.IsArray || csSubParameter.IsComObject || csSubParameter.HasPointer) { csSubParameter.PublicType = intPtrType; csSubParameter.IsArray = false; csSubParameter.Attribute = CsParameterAttribute.In; } } interfaceType.Add(rawMethod); } }