public InterfaceTransform(
            NamingRulesManager namingRules,
            Logger logger,
            GlobalNamespaceProvider globalNamespace,
            ITransformPreparer <CppMethod, CsMethod> methodPreparer,
            ITransformer <CsMethod> methodTransformer,
            TypeRegistry typeRegistry,
            NamespaceRegistry namespaceRegistry)
            : base(namingRules, logger)
        {
            MethodPreparer         = methodPreparer;
            MethodTransformer      = methodTransformer;
            this.typeRegistry      = typeRegistry;
            this.namespaceRegistry = namespaceRegistry;
            propertyBuilder        = new PropertyBuilder(globalNamespace);
            methodOverloadBuilder  = new MethodOverloadBuilder(globalNamespace, typeRegistry);

            CppObjectType = new CsInterface {
                Name = globalNamespace.GetTypeName(WellKnownName.CppObject)
            };
            DefaultCallbackable = new CsInterface
            {
                Name       = globalNamespace.GetTypeName(WellKnownName.ICallbackable),
                ShadowName = globalNamespace.GetTypeName(WellKnownName.CppObjectShadow),
                VtblName   = globalNamespace.GetTypeName(WellKnownName.CppObjectVtbl)
            };
        }
示例#2
0
        /// <summary>
        /// Processes the specified method.
        /// </summary>
        /// <param name="method">The method.</param>
        private void ProcessMethod(CsCallable method)
        {
            var cppMethod = (CppCallable)method.CppElement;

            method.Name = NamingRules.Rename(cppMethod);

            // For methods, the tag "type" is only used for return type
            // So we are overriding the return type here
            var methodRule = cppMethod.GetMappingRule();

            if (methodRule.MappingType != null)
            {
                cppMethod.ReturnValue.Rule = new MappingRule {
                    MappingType = methodRule.MappingType
                }
            }
            ;

            // Get the inferred return type
            method.ReturnValue = factory.Create(cppMethod.ReturnValue);

            if (method.ReturnValue.PublicType is CsInterface iface && iface.IsCallback)
            {
                method.ReturnValue.PublicType = iface.GetNativeImplementationOrThis();
            }

            // Hide return type only if it is a HRESULT and AlwaysReturnHResult is false
            if (method.CheckReturnType && method.ReturnValue.PublicType != null &&
                method.ReturnValue.PublicType.QualifiedName == globalNamespace.GetTypeName(WellKnownName.Result))
            {
                method.HideReturnType = !method.AlwaysReturnHResult;
            }

            // Iterates on parameters to convert them to C# parameters
            foreach (var cppParameter in cppMethod.Parameters)
            {
                var paramMethod = factory.Create(cppParameter);

                paramMethod.Name = NamingRules.Rename(cppParameter);

                method.Add(paramMethod);
            }
        }
示例#3
0
        private bool ValidateGetter(CsMethod getter)
        {
            if (getter == null)
            {
                return(true);
            }

            if ((getter.ReturnValue.PublicType.Name == globalNamespace.GetTypeName(WellKnownName.Result) || !getter.HasReturnType) &&
                getter.Parameters.Count == 1 &&
                getter.Parameters[0].IsOut && !getter.Parameters[0].IsArray)
            {
                return(true);
            }
            else if (getter.Parameters.Count == 0 && getter.HasReturnType)
            {
                return(true);
            }
            return(false);
        }
        private InteropType GetInteropTypeForParameter(CsParameter param)
        {
            InteropType interopType;
            var         publicName = param.PublicType.QualifiedName;

            if (publicName == provider.GetTypeName(WellKnownName.PointerSize))
            {
                interopType = typeof(void *);
            }
            else if (param.HasPointer)
            {
                interopType = typeof(void *);
            }
            else if (param.MarshalType is CsFundamentalType marshalFundamental)
            {
                var type = marshalFundamental.Type;
                if (type == typeof(IntPtr))
                {
                    type = typeof(void *);
                }
                interopType = type;
            }
            else if (param.PublicType is CsFundamentalType publicFundamental)
            {
                var type = publicFundamental.Type;
                if (type == typeof(IntPtr))
                {
                    type = typeof(void *);
                }
                interopType = type;
            }
            else if (param.PublicType is CsStruct csStruct)
            {
                // If parameter is a struct, then a LocalInterop is needed
                if (csStruct.HasMarshalType)
                {
                    interopType = $"{csStruct.QualifiedName}.__Native";
                }
                else
                {
                    interopType = csStruct.QualifiedName;
                }
            }
            else if (param.PublicType is CsEnum csEnum)
            {
                interopType = csEnum.UnderlyingType.Type;
            }
            else
            {
                interopType = null;
            }

            return(interopType);
        }
        public InteropSignatureTransform(GlobalNamespaceProvider provider, Logger logger)
        {
            this.provider = provider;
            this.logger   = logger;

            returnTypeOverrides = new Dictionary <string, SignatureInteropTypeOverride>
            {
                { provider.GetTypeName(WellKnownName.Result), typeof(int) },
                { provider.GetTypeName(WellKnownName.PointerSize), typeof(void *) }
            };

            windowsOnlyReturnTypeOverrides = new Dictionary <string, SignatureInteropTypeOverride>
            {
                {
                    provider.GetTypeName(WellKnownName.NativeLong),
                    new SignatureInteropTypeOverride(typeof(int), InteropMethodSignatureFlags.CastToNativeLong)
                },
                {
                    provider.GetTypeName(WellKnownName.NativeULong),
                    new SignatureInteropTypeOverride(typeof(uint), InteropMethodSignatureFlags.CastToNativeULong)
                }
            };

            systemvOnlyReturnTypeOverrides = new Dictionary <string, SignatureInteropTypeOverride>
            {
                {
                    provider.GetTypeName(WellKnownName.NativeLong),
                    new SignatureInteropTypeOverride(typeof(IntPtr), InteropMethodSignatureFlags.CastToNativeLong)
                },
                {
                    provider.GetTypeName(WellKnownName.NativeULong),
                    new SignatureInteropTypeOverride(typeof(UIntPtr), InteropMethodSignatureFlags.CastToNativeULong)
                }
            };
        }
示例#6
0
        public CsMethod CreateInterfaceArrayOverload(CsMethod original)
        {
            // Create a new method and transforms all array of CppObject to InterfaceArray<CppObject>
            var newMethod = (CsMethod)original.Clone();

            foreach (var csParameter in newMethod.PublicParameters)
            {
                if (!csParameter.IsInInterfaceArrayLike)
                {
                    continue;
                }

                csParameter.PublicType = new CsInterfaceArray(
                    (CsInterface)csParameter.PublicType,
                    globalNamespace.GetTypeName(WellKnownName.InterfaceArray)
                    );

                csParameter.MarshalType = TypeRegistry.IntPtr;
            }
            return(newMethod);
        }
        public InteropSignatureTransform(GlobalNamespaceProvider provider, Logger logger)
        {
            this.provider = provider;
            this.logger   = logger;

            returnTypeOverrides = new Dictionary <string, SignatureInteropTypeOverride>
            {
                {
                    provider.GetTypeName(WellKnownName.Result),
                    TypeRegistry.Int32
                },
                {
                    provider.GetTypeName(WellKnownName.PointerSize),
                    TypeRegistry.VoidPtr
                }
            };

            const InteropMethodSignatureFlags castToNativeLong  = InteropMethodSignatureFlags.CastToNativeLong;
            const InteropMethodSignatureFlags castToNativeULong = InteropMethodSignatureFlags.CastToNativeULong;

            windowsOnlyReturnTypeOverrides = new Dictionary <string, SignatureInteropTypeOverride>
            {
                {
                    provider.GetTypeName(WellKnownName.NativeLong),
                    new SignatureInteropTypeOverride(TypeRegistry.Int32, castToNativeLong)
                },
                {
                    provider.GetTypeName(WellKnownName.NativeULong),
                    new SignatureInteropTypeOverride(TypeRegistry.UInt32, castToNativeULong)
                }
            };

            systemvOnlyReturnTypeOverrides = new Dictionary <string, SignatureInteropTypeOverride>
            {
                {
                    provider.GetTypeName(WellKnownName.NativeLong),
                    new SignatureInteropTypeOverride(TypeRegistry.IntPtr, castToNativeLong)
                },
                {
                    provider.GetTypeName(WellKnownName.NativeULong),
                    new SignatureInteropTypeOverride(TypeRegistry.UIntPtr, castToNativeULong)
                }
            };
        }
示例#8
0
 public bool IsWellKnownType(GlobalNamespaceProvider globalNamespace, WellKnownName name) =>
 QualifiedName == globalNamespace.GetTypeName(name);
示例#9
0
        public override IEnumerable <MemberDeclarationSyntax> GenerateCode(CsCallable csElement)
        {
            // Documentation
            var documentationTrivia = GenerateDocumentationTrivia(csElement);

            // method signature
            var methodDeclaration = MethodDeclaration(ParseTypeName(csElement.PublicReturnTypeQualifiedName), csElement.Name)
                                    .WithModifiers(TokenList(ParseTokens(csElement.VisibilityName)).Add(Token(SyntaxKind.UnsafeKeyword)))
                                    .WithParameterList(
                ParameterList(
                    SeparatedList(
                        csElement.PublicParameters.Select(param =>
                                                          Generators.Marshalling.GetMarshaller(param).GenerateManagedParameter(param)
                                                          .WithDefault(param.DefaultValue == null ? default
                                        : EqualsValueClause(ParseExpression(param.DefaultValue)))
                                                          )
                        )
                    )
                )
                                    .WithLeadingTrivia(Trivia(documentationTrivia));

            if (csElement.SignatureOnly)
            {
                yield return(methodDeclaration
                             .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))
                             .WithModifiers(TokenList()));

                yield break;
            }

            var statements = new List <StatementSyntax>();

            foreach (var param in csElement.Parameters)
            {
                if (param.Relation == null)
                {
                    if (param.UsedAsReturn)
                    {
                        statements.Add(GenerateManagedHiddenMarshallableProlog(param));
                    }
                    statements.AddRange(Generators.Marshalling.GetMarshaller(param).GenerateManagedToNativeProlog(param));
                }
                else
                {
                    statements.Add(GenerateManagedHiddenMarshallableProlog(param));

                    if (!ValidRelationInScenario(param.Relation))
                    {
                        logger.Error(LoggingCodes.InvalidRelationInScenario, $"The relation \"{param.Relation}\" is invalid in a method/function.");
                        continue;
                    }

                    var             marshaller = Generators.Marshalling.GetRelationMarshaller(param.Relation);
                    StatementSyntax marshalToNative;
                    var             relatedMarshallableName = (param.Relation as IHasRelatedMarshallable)?.RelatedMarshallableName;
                    if (relatedMarshallableName is null)
                    {
                        marshalToNative = marshaller.GenerateManagedToNative(null, param);
                    }
                    else
                    {
                        marshalToNative = marshaller.GenerateManagedToNative(
                            csElement.Parameters.First(p => p.CppElementName == relatedMarshallableName),
                            param);
                    }

                    if (marshalToNative != null)
                    {
                        statements.Add(marshalToNative);
                    }

                    statements.AddRange(Generators.Marshalling.GetMarshaller(param).GenerateManagedToNativeProlog(param));
                }
            }

            if (csElement.HasReturnType)
            {
                statements.Add(GenerateManagedHiddenMarshallableProlog(csElement.ReturnValue));
                statements.AddRange(
                    Generators.Marshalling.GetMarshaller(csElement.ReturnValue)
                    .GenerateManagedToNativeProlog(csElement.ReturnValue));
            }


            foreach (var param in csElement.Parameters)
            {
                if (param.IsIn || param.IsRefIn || param.IsRef)
                {
                    var marshaller      = Generators.Marshalling.GetMarshaller(param);
                    var marshalToNative = marshaller.GenerateManagedToNative(param, true);
                    if (marshalToNative != null)
                    {
                        statements.Add(marshalToNative);
                    }
                }
            }

            var fixedStatements = csElement.PublicParameters
                                  .Select(param => Generators.Marshalling.GetMarshaller(param).GeneratePin(param))
                                  .Where(stmt => stmt != null).ToList();

            var callStmt = GeneratorHelpers.GetPlatformSpecificStatements(
                globalNamespace,
                Generators.Config,
                csElement.InteropSignatures.Keys,
                (platform) =>
                ExpressionStatement(
                    Generators.NativeInvocation.GenerateCode((csElement, platform, csElement.InteropSignatures[platform]))));

            var fixedStatement = fixedStatements.FirstOrDefault()?.WithStatement(callStmt);

            foreach (var statement in fixedStatements.Skip(1))
            {
                fixedStatement = statement.WithStatement(fixedStatement);
            }

            statements.Add(fixedStatement ?? callStmt);

            foreach (var param in csElement.Parameters)
            {
                if (param.IsRef || param.IsOut)
                {
                    var marshaller        = Generators.Marshalling.GetMarshaller(param);
                    var marshalFromNative = marshaller.GenerateNativeToManaged(param, true);
                    if (marshalFromNative != null)
                    {
                        statements.Add(marshalFromNative);
                    }
                }
            }

            if (csElement.HasReturnType)
            {
                var marshaller        = Generators.Marshalling.GetMarshaller(csElement.ReturnValue);
                var marshalReturnType = marshaller.GenerateNativeToManaged(csElement.ReturnValue, true);
                if (marshalReturnType != null)
                {
                    statements.Add(marshalReturnType);
                }
            }

            statements.AddRange(csElement.Parameters
                                .Where(param => !param.IsOut)
                                .Select(param => Generators.Marshalling.GetMarshaller(param).GenerateNativeCleanup(param, true))
                                .Where(param => param != null));


            if ((csElement.ReturnValue.PublicType.Name == globalNamespace.GetTypeName(WellKnownName.Result)) && csElement.CheckReturnType)
            {
                statements.Add(ExpressionStatement(
                                   InvocationExpression(
                                       MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                              IdentifierName(csElement.ReturnValue.Name),
                                                              IdentifierName("CheckError")))));
            }

            // Return
            if (csElement.HasPublicReturnType)
            {
                if (csElement.HasReturnTypeParameter || csElement.ForceReturnType || !csElement.HideReturnType)
                {
                    statements.Add(ReturnStatement(IdentifierName(csElement.ReturnName)));
                }
            }

            yield return(methodDeclaration.WithBody(Block(statements)));
        }
        /// <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);
        }
示例#11
0
        public override IEnumerable <MemberDeclarationSyntax> GenerateCode(CsCallable csElement)
        {
            // Documentation
            var documentationTrivia = GenerateDocumentationTrivia(csElement);

            // method signature
            var methodDeclaration = MethodDeclaration(ParseTypeName(csElement.PublicReturnTypeQualifiedName), csElement.Name)
                                    .WithModifiers(TokenList(ParseTokens(csElement.VisibilityName)).Add(Token(SyntaxKind.UnsafeKeyword)))
                                    .WithParameterList(
                ParameterList(
                    SeparatedList(
                        csElement.PublicParameters.Select(param =>
                                                          Generators.Marshalling.GetMarshaller(param).GenerateManagedParameter(param)
                                                          .WithDefault(param.DefaultValue == null ? default
                                        : EqualsValueClause(ParseExpression(param.DefaultValue)))
                                                          )
                        )
                    )
                )
                                    .WithLeadingTrivia(Trivia(documentationTrivia));

            if (csElement.SignatureOnly)
            {
                yield return(methodDeclaration
                             .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))
                             .WithModifiers(TokenList()));

                yield break;
            }

            var statements = new List <StatementSyntax>();

            foreach (var param in csElement.Parameters)
            {
                if (param.UsedAsReturn)
                {
                    statements.Add(GenerateManagedReturnProlog(param));
                }
                statements.AddRange(Generators.Marshalling.GetMarshaller(param).GenerateManagedToNativeProlog(param));
            }

            if (csElement.HasReturnType)
            {
                statements.Add(GenerateManagedReturnProlog(csElement.ReturnValue));
                statements.AddRange(
                    Generators.Marshalling.GetMarshaller(csElement.ReturnValue)
                    .GenerateManagedToNativeProlog(csElement.ReturnValue));
            }


            foreach (var param in csElement.Parameters)
            {
                if (param.IsIn || param.IsRefIn || param.IsRef)
                {
                    var marshaller      = Generators.Marshalling.GetMarshaller(param);
                    var marshalToNative = marshaller.GenerateManagedToNative(param, true);
                    if (marshalToNative != null)
                    {
                        statements.Add(marshalToNative);
                    }
                }
            }

            var fixedStatements = csElement.PublicParameters
                                  .Select(param => Generators.Marshalling.GetMarshaller(param).GeneratePin(param))
                                  .Where(stmt => stmt != null).ToList();

            var callStmt = ExpressionStatement(Generators.NativeInvocation.GenerateCode(csElement));

            var fixedStatement = fixedStatements.FirstOrDefault()?.WithStatement(callStmt);

            foreach (var statement in fixedStatements.Skip(1))
            {
                fixedStatement = statement.WithStatement(fixedStatement);
            }

            statements.Add((StatementSyntax)fixedStatement ?? callStmt);

            foreach (var param in csElement.Parameters)
            {
                if (param.IsRef || param.IsOut)
                {
                    var marshaller        = Generators.Marshalling.GetMarshaller(param);
                    var marshalFromNative = marshaller.GenerateNativeToManaged(param, true);
                    if (marshalFromNative != null)
                    {
                        statements.Add(marshalFromNative);
                    }
                }
            }

            if (csElement.HasReturnType)
            {
                var marshaller        = Generators.Marshalling.GetMarshaller(csElement.ReturnValue);
                var marshalReturnType = marshaller.GenerateNativeToManaged(csElement.ReturnValue, true);
                if (marshalReturnType != null)
                {
                    statements.Add(marshalReturnType);
                }
            }

            statements.AddRange(csElement.Parameters
                                .Where(param => !param.IsOut)
                                .Select(param => Generators.Marshalling.GetMarshaller(param).GenerateNativeCleanup(param, true))
                                .Where(param => param != null));


            if ((csElement.ReturnValue.PublicType.Name == globalNamespace.GetTypeName(WellKnownName.Result)) && csElement.CheckReturnType)
            {
                statements.Add(ExpressionStatement(
                                   InvocationExpression(
                                       MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                              IdentifierName(csElement.ReturnValue.Name),
                                                              IdentifierName("CheckError")))));
            }

            // Return
            if (csElement.HasPublicReturnType)
            {
                if (csElement.HasReturnTypeParameter || csElement.ForceReturnType || !csElement.HideReturnType)
                {
                    statements.Add(ReturnStatement(IdentifierName(csElement.ReturnName)));
                }
            }

            yield return(methodDeclaration.WithBody(Block(statements)));
        }