Exemple #1
0
        /// <summary>
        /// Registers the native interop signature.
        /// </summary>
        /// <param name="callable">The cs method.</param>
        private void RegisterNativeInteropSignature(CsCallable callable, bool isFunction)
        {
            // Tag if the method is a function
            var cSharpInteropCalliSignature = new InteropMethodSignature
            {
                IsFunction        = isFunction,
                CallingConvention = callable.CallingConvention
            };

            InitSignatureWithReturnType(callable, cSharpInteropCalliSignature);

            // Handle Parameters
            foreach (var param in callable.Parameters)
            {
                var(interopType, isLocal) = GetInteropTypeForParameter(param);

                if (interopType == null)
                {
                    Logger.Error(LoggingCodes.InvalidMethodParameterType, "Invalid parameter {0} for method {1}", param.PublicType.QualifiedName, callable.CppElement);
                }

                cSharpInteropCalliSignature.IsLocal |= isLocal;

                cSharpInteropCalliSignature.ParameterTypes.Add(interopType);
            }

            var assembly = callable.GetParent <CsAssembly>();

            cSharpInteropCalliSignature = assembly.Interop.Add(cSharpInteropCalliSignature);

            callable.Interop = cSharpInteropCalliSignature;
        }
Exemple #2
0
 private void InitSignatureWithReturnType(CsCallable callable, InteropMethodSignature cSharpInteropCalliSignature)
 {
     // Handle Return Type parameter
     // MarshalType.Type == null, then check that it is a structure
     if (callable.ReturnValue.PublicType is CsStruct || callable.ReturnValue.PublicType is CsEnum)
     {
         // Return type and 1st parameter are implicitly a pointer to the structure to fill
         if (callable.IsReturnStructLarge)
         {
             cSharpInteropCalliSignature.ReturnType = typeof(void *);
             cSharpInteropCalliSignature.ParameterTypes.Add(typeof(void *));
         }
         else
         {
             var returnQualifiedName = callable.ReturnValue.PublicType.QualifiedName;
             if (returnQualifiedName == globalNamespace.GetTypeName(WellKnownName.Result))
             {
                 cSharpInteropCalliSignature.ReturnType = typeof(int);
             }
             else if (returnQualifiedName == globalNamespace.GetTypeName(WellKnownName.PointerSize))
             {
                 cSharpInteropCalliSignature.ReturnType = typeof(void *);
             }
             else if (callable.ReturnValue.HasNativeValueType)
             {
                 cSharpInteropCalliSignature.ReturnType = $"{callable.ReturnValue.MarshalType.QualifiedName}.__Native";
             }
             else
             {
                 cSharpInteropCalliSignature.ReturnType = callable.ReturnValue.MarshalType.QualifiedName;
             }
         }
     }
     else if (callable.ReturnValue.MarshalType is CsFundamentalType fundamentalReturn)
     {
         cSharpInteropCalliSignature.ReturnType = fundamentalReturn.Type;
     }
     else if (callable.ReturnValue.HasPointer)
     {
         if (callable.ReturnValue.IsInterface)
         {
             cSharpInteropCalliSignature.ReturnType = typeof(IntPtr);
         }
         else
         {
             cSharpInteropCalliSignature.ReturnType = typeof(void *);
         }
     }
     else
     {
         Logger.Error(LoggingCodes.InvalidMethodReturnType, "Invalid return type {0} for method {1}", callable.ReturnValue.PublicType.QualifiedName, callable.CppElement);
     }
 }
        private void InitSignatureWithReturnType(CsCallable callable, InteropMethodSignature cSharpInteropCalliSignature, PlatformDetectionType platform)
        {
            Debug.Assert((platform & (PlatformDetectionType.IsWindows | PlatformDetectionType.IsItaniumSystemV)) != (PlatformDetectionType.IsWindows | PlatformDetectionType.IsItaniumSystemV) || !callable.IsReturnStructLarge);
            var platformSpecificReturnTypeOverrides = (platform & PlatformDetectionType.IsWindows) != 0
                ? windowsOnlyReturnTypeOverrides
                : systemvOnlyReturnTypeOverrides;

            // Handle Return Type parameter
            // MarshalType.Type == null, then check that it is a structure
            if (callable.ReturnValue.PublicType is CsStruct || callable.ReturnValue.PublicType is CsEnum)
            {
                var returnQualifiedName = callable.ReturnValue.PublicType.QualifiedName;
                if (returnTypeOverrides.TryGetValue(returnQualifiedName, out var interopType))
                {
                    cSharpInteropCalliSignature.ReturnType = interopType.NewType;
                    cSharpInteropCalliSignature.Flags     |= interopType.SetFlags;
                }
                else if (platformSpecificReturnTypeOverrides.TryGetValue(returnQualifiedName, out interopType))
                {
                    cSharpInteropCalliSignature.ReturnType = interopType.NewType;
                    cSharpInteropCalliSignature.Flags     |= interopType.SetFlags;
                }
                else if (callable.ReturnValue.HasNativeValueType)
                {
                    cSharpInteropCalliSignature.ReturnType = $"{callable.ReturnValue.MarshalType.QualifiedName}.__Native";
                }
                else
                {
                    cSharpInteropCalliSignature.ReturnType = callable.ReturnValue.MarshalType.QualifiedName;
                }
            }
            else if (callable.ReturnValue.MarshalType is CsFundamentalType fundamentalReturn)
            {
                cSharpInteropCalliSignature.ReturnType = fundamentalReturn.Type;
            }
            else if (callable.ReturnValue.HasPointer)
            {
                if (callable.ReturnValue.IsInterface)
                {
                    cSharpInteropCalliSignature.ReturnType = typeof(IntPtr);
                }
                else
                {
                    cSharpInteropCalliSignature.ReturnType = typeof(void *);
                }
            }
            else
            {
                cSharpInteropCalliSignature.ReturnType = callable.ReturnValue.PublicType.QualifiedName;
                logger.Error(LoggingCodes.InvalidMethodReturnType, "Invalid return type {0} for method {1}", callable.ReturnValue.PublicType.QualifiedName, callable.CppElement);
            }
        }
        private void InitCalliSignatureParameters(CsCallable callable, InteropMethodSignature cSharpInteropCalliSignature)
        {
            foreach (var param in callable.Parameters)
            {
                var interopType = GetInteropTypeForParameter(param);

                if (interopType == null)
                {
                    logger.Error(LoggingCodes.InvalidMethodParameterType, "Invalid parameter {0} for method {1}", param.PublicType.QualifiedName, callable.CppElement);
                }

                cSharpInteropCalliSignature.ParameterTypes.Add(interopType);
            }
        }
        private InteropMethodSignature GetNativeInteropSignatureWithForcedReturnBuffer(CsCallable callable, bool isFunction)
        {
            var cSharpInteropCalliSignature = new InteropMethodSignature
            {
                IsFunction            = isFunction,
                CallingConvention     = callable.CallingConvention,
                ForcedReturnBufferSig = true,
                ReturnType            = typeof(void *),
                ParameterTypes        = { typeof(void *) }
            };

            InitCalliSignatureParameters(callable, cSharpInteropCalliSignature);

            return(cSharpInteropCalliSignature);
        }
Exemple #6
0
    private void InitSignatureWithReturnType(CsCallable callable,
                                             InteropMethodSignature cSharpInteropCalliSignature,
                                             PlatformDetectionType platform)
    {
        var returnType = CoerceToBlittable(GetInteropTypeForReturnValue(callable.ReturnValue, platform));

        if (returnType is null)
        {
            Logger.Error(LoggingCodes.InvalidMethodReturnType, "Invalid return type {0} for method {1}",
                         callable.ReturnValue.PublicType.QualifiedName, callable.CppElement);
            returnType = callable.ReturnValue.PublicType.QualifiedName;
        }

        cSharpInteropCalliSignature.ReturnType = returnType;
    }
        /// <summary>
        /// Registers the native interop signature.
        /// </summary>
        /// <param name="callable">The cs method.</param>
        private InteropMethodSignature GetNativeInteropSignature(CsCallable callable, bool isFunction, PlatformDetectionType platform)
        {
            // Tag if the method is a function
            var cSharpInteropCalliSignature = new InteropMethodSignature
            {
                IsFunction        = isFunction,
                CallingConvention = callable.CallingConvention
            };

            InitSignatureWithReturnType(callable, cSharpInteropCalliSignature, platform);

            // Handle Parameters
            InitCalliSignatureParameters(callable, cSharpInteropCalliSignature);

            return(cSharpInteropCalliSignature);
        }
        private InteropMethodSignature GetNativeInteropSignatureWithForcedReturnBuffer(CsCallable callable, bool isFunction)
        {
            var cSharpInteropCalliSignature = new InteropMethodSignature
            {
                IsFunction        = isFunction,
                CallingConvention = callable.CallingConvention,
                Flags             = InteropMethodSignatureFlags.ForcedReturnBufferSig
            };

            cSharpInteropCalliSignature.ReturnType = typeof(void *);
            cSharpInteropCalliSignature.ParameterTypes.Add(typeof(void *));

            InitCalliSignatureParameters(callable, cSharpInteropCalliSignature);

            return(cSharpInteropCalliSignature);
        }
        private InteropMethodSignature GetNativeInteropSignatureWithForcedReturnBuffer(
            CsCallable callable, bool isFunction)
        {
            var cSharpInteropCalliSignature = new InteropMethodSignature
            {
                IsFunction            = isFunction,
                CallingConvention     = callable.CppCallingConvention,
                ForcedReturnBufferSig = true,
                ReturnType            = TypeRegistry.VoidPtr,
                ParameterTypes        = { new InteropMethodSignatureParameter(TypeRegistry.VoidPtr, callable.ReturnValue, "returnSlot") }
            };

            InitCalliSignatureParameters(callable, cSharpInteropCalliSignature);

            return(cSharpInteropCalliSignature);
        }
        private void InitSignatureWithReturnType(CsCallable callable,
                                                 InteropMethodSignature cSharpInteropCalliSignature,
                                                 PlatformDetectionType platform)
        {
            InteropMethodSignatureFlags flags = default;

            var returnType = GetInteropTypeForReturnValue(callable.ReturnValue, platform, ref flags);

            if (returnType == null)
            {
                logger.Error(LoggingCodes.InvalidMethodReturnType, "Invalid return type {0} for method {1}",
                             callable.ReturnValue.PublicType.QualifiedName, callable.CppElement);
                returnType = callable.ReturnValue.PublicType.QualifiedName;
            }

            if (flags != default)
            {
                cSharpInteropCalliSignature.Flags |= flags;
            }

            cSharpInteropCalliSignature.ReturnType = returnType;
        }
Exemple #11
0
        /// <summary>
        /// Registers the native interop signature.
        /// </summary>
        /// <param name="csMethod">The cs method.</param>
        private void RegisterNativeInteropSignature(CsMethod csMethod)
        {
            // Tag if the method is a function
            var cSharpInteropCalliSignature = new InteropMethodSignature {
                IsFunction = (csMethod is CsFunction)
            };

            // Handle Return Type parameter
            // MarshalType.Type == null, then check that it is a structure
            if (csMethod.ReturnType.PublicType is CsStruct || csMethod.ReturnType.PublicType is CsEnum)
            {
                // Return type and 1st parameter are implicitly a pointer to the structure to fill
                if (csMethod.IsReturnStructLarge)
                {
                    cSharpInteropCalliSignature.ReturnType = typeof(void *);
                    cSharpInteropCalliSignature.ParameterTypes.Add(typeof(void *));
                }
                else
                {
                    // Patch for Mono bug with structs marshalling and calli.
                    var returnQualifiedName = csMethod.ReturnType.PublicType.QualifiedName;
                    if (returnQualifiedName == Manager.GlobalNamespace.GetTypeName("Result"))
                    {
                        cSharpInteropCalliSignature.ReturnType = typeof(int);
                    }
                    else if (returnQualifiedName == Manager.GlobalNamespace.GetTypeName("PointerSize"))
                    {
                        cSharpInteropCalliSignature.ReturnType = typeof(void *);
                    }
                    else
                    {
                        cSharpInteropCalliSignature.ReturnType = csMethod.ReturnType.PublicType.QualifiedName;
                    }
                }
            }
            else if (csMethod.ReturnType.MarshalType.Type != null)
            {
                Type type = csMethod.ReturnType.MarshalType.Type;
                cSharpInteropCalliSignature.ReturnType = type;
            }
            else
            {
                throw new ArgumentException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Invalid return type {0} for method {1}", csMethod.ReturnType.PublicType.QualifiedName, csMethod.CppElement));
            }

            // Handle Parameters
            foreach (var param in csMethod.Parameters)
            {
                InteropType interopType;
                string      publicName = param.PublicType.QualifiedName;
                // Patch for Mono bug with structs marshalling and calli.
                if (publicName == Manager.GlobalNamespace.GetTypeName("PointerSize"))
                {
                    interopType = typeof(void *);
                }
                else if (param.MarshalType.Type == null)
                {
                    if (param.PublicType is CsStruct)
                    {
                        // If parameter is a struct, then a LocalInterop is needed
                        interopType = param.PublicType.QualifiedName;
                        cSharpInteropCalliSignature.IsLocal = true;
                    }
                    else
                    {
                        throw new ArgumentException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Invalid parameter {0} for method {1}", param.PublicType.QualifiedName, csMethod.CppElement));
                    }
                }
                else
                {
                    Type type = param.MarshalType.Type;
                    // Patch for Mono bug with structs marshalling and calli.
                    if (type == typeof(IntPtr))
                    {
                        type = typeof(void *);
                    }
                    interopType = type;
                }

                cSharpInteropCalliSignature.ParameterTypes.Add(interopType);
            }

            var assembly = csMethod.GetParent <CsAssembly>();

            cSharpInteropCalliSignature = assembly.Interop.Add(cSharpInteropCalliSignature);

            csMethod.Interop = cSharpInteropCalliSignature;
        }
Exemple #12
0
 private DelegateDeclarationSyntax GenerateDelegateDeclaration(CsCallable csElement, PlatformDetectionType platform, InteropMethodSignature sig)
 {
     return(DelegateDeclaration(ParseTypeName(sig.ReturnType.TypeName), VtblGenerator.GetMethodDelegateName(csElement, platform))
            .AddAttributeLists(
                AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            ParseName("System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute"))
                        .AddArgumentListArguments(
                            AttributeArgument(
                                MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    MemberAccessExpression(
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        MemberAccessExpression(
                                            SyntaxKind.SimpleMemberAccessExpression,
                                            MemberAccessExpression(
                                                SyntaxKind.SimpleMemberAccessExpression,
                                                IdentifierName("System"),
                                                IdentifierName("Runtime")),
                                            IdentifierName("InteropServices")),
                                        IdentifierName("CallingConvention")),
                                    IdentifierName(sig.CallingConvention.ToManagedCallingConventionName())))))))
            .WithParameterList(
                ParameterList(
                    (csElement is CsMethod ?
                     SingletonSeparatedList(
                         Parameter(Identifier("thisObject"))
                         .WithType(ParseTypeName("System.IntPtr")))
                 : default)
Exemple #13
0
    private IEnumerable <(ArgumentSyntax Argument, TypeSyntax Type)> IterateNativeArguments(bool isMethod,
                                                                                            InteropMethodSignature interopSig)
    {
        if (isMethod)
        {
            yield return(NativePointerArgument, GeneratorHelpers.IntPtrType);
        }

        (ArgumentSyntax, TypeSyntax) ParameterSelector(InteropMethodSignatureParameter param)
        {
            var csElement = param.Item;

            return(GetMarshaller(csElement).GenerateNativeArgument(csElement), param.InteropTypeSyntax);
        }

        foreach (var parameter in interopSig.ParameterTypes)
        {
            yield return(ParameterSelector(parameter));
        }
    }
Exemple #14
0
        public ExpressionSyntax GenerateCall(CsCallable callable, PlatformDetectionType platform,
                                             InteropMethodSignature interopSig)
        {
            var arguments = IterateNativeArguments(callable, interopSig).ToArray();

            ElementAccessExpressionSyntax vtblAccess = null;

            if (callable is CsMethod method)
            {
                var windowsOffsetExpression =
                    LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(method.WindowsOffset));
                var nonWindowsOffsetExpression =
                    LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(method.Offset));

                ExpressionSyntax vtableOffsetExpression;
                if ((platform & PlatformDetectionType.Any) == PlatformDetectionType.Any &&
                    method.Offset != method.WindowsOffset)
                {
                    vtableOffsetExpression = ConditionalExpression(
                        MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            GlobalNamespace.GetTypeNameSyntax(WellKnownName.PlatformDetection),
                            IdentifierName("Is" + nameof(PlatformDetectionType.Windows))),
                        windowsOffsetExpression,
                        nonWindowsOffsetExpression);
                }
                else if ((platform & PlatformDetectionType.Windows) != 0)
                {
                    vtableOffsetExpression = windowsOffsetExpression;
                }
                else
                {
                    vtableOffsetExpression = nonWindowsOffsetExpression;
                }

                vtblAccess = ElementAccessExpression(
                    ThisExpression(),
                    BracketedArgumentList(
                        SingletonSeparatedList(
                            Argument(
                                method.CustomVtbl
                                    ? MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    ThisExpression(),
                                    IdentifierName($"{callable.Name}__vtbl_index")
                                    )
                                    : vtableOffsetExpression
                                )
                            )
                        )
                    );
            }

            ExpressionSyntax FnPtrCall()
            {
                var fnptrParameters = arguments
                                      .Select(x => x.Type)
                                      .Append(ParseTypeName(interopSig.ReturnType.TypeName))
                                      .Select(FunctionPointerParameter);

                return(GeneratorHelpers.CastExpression(
                           FunctionPointerType(
                               FunctionPointerCallingConvention(
                                   Token(SyntaxKind.UnmanagedKeyword),
                                   FunctionPointerUnmanagedCallingConventionList(
                                       SingletonSeparatedList(
                                           FunctionPointerUnmanagedCallingConvention(
                                               Identifier(callable.CppCallingConvention.ToCallConvShortName())
                                               )
                                           )
                                       )
                                   ),
                               FunctionPointerParameterList(SeparatedList(fnptrParameters))
                               ),
                           vtblAccess
                           ));
            }

            var what = callable switch
            {
                CsFunction => IdentifierName(
                    callable.CppElementName + GeneratorHelpers.GetPlatformSpecificSuffix(platform)
                    ),
                CsMethod => GeneratorHelpers.WrapInParentheses(FnPtrCall()),
                _ => throw new ArgumentOutOfRangeException()
            };

            ExpressionSyntax call = InvocationExpression(
                what,
                ArgumentList(SeparatedList(arguments.Select(x => x.Argument)))
                );

            if (interopSig.CastToNativeLong)
            {
                call = CastExpression(GlobalNamespace.GetTypeNameSyntax(WellKnownName.NativeLong), call);
            }

            if (interopSig.CastToNativeULong)
            {
                call = CastExpression(GlobalNamespace.GetTypeNameSyntax(WellKnownName.NativeULong), call);
            }

            if (interopSig.ForcedReturnBufferSig || !callable.HasReturnType)
            {
                return(call);
            }

            return(AssignmentExpression(
                       SyntaxKind.SimpleAssignmentExpression,
                       GetMarshaller(callable.ReturnValue).GeneratesMarshalVariable(callable.ReturnValue)
                    ? MarshallerBase.GetMarshalStorageLocation(callable.ReturnValue)
                    : IdentifierName(callable.ReturnValue.Name),
                       call
                       ));
        }
        private IEnumerable <(ArgumentSyntax Argument, TypeSyntax Type)> IterateNativeArguments(CsCallable callable,
                                                                                                InteropMethodSignature interopSig)
        {
            if (callable is CsMethod)
            {
                var ptr = MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName("_nativePointer")
                    );

                yield return(Argument(ptr), VoidPtr);
            }

            (ArgumentSyntax, TypeSyntax) ParameterSelector(InteropMethodSignatureParameter param)
            {
                var csElement  = param.Item;
                var marshaller = generators.Marshalling.GetMarshaller(csElement);

                return(marshaller.GenerateNativeArgument(csElement), param.InteropTypeSyntax);
            }

            foreach (var parameter in interopSig.ParameterTypes)
            {
                yield return(ParameterSelector(parameter));
            }
        }