/// <inheritdoc />
        public override IntrospectiveMethodInfo GeneratePassthroughDefinition(PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            if (!workUnit.Definition.ReturnType.GenericTypeArguments[0].IsValueType)
            {
                // Span<byte> is used because unbound generics are not allowed inside a nameof, and it still results as just 'Span'
                throw new NotSupportedException($"Method is not a {nameof(ValueType)} and cannot be marshaled as a {nameof(Span<byte>)}. Marshalling {nameof(Span<byte>)}" +
                                                $"requires the marshaled type T in {nameof(Span<byte>)}<T> to be a {nameof(ValueType)}");
            }

            var definition = workUnit.Definition;

            Type newReturnType = definition.ReturnType.GenericTypeArguments[0].MakePointerType();

            /* TODO? Add marshaling for Span<> params */

            Type[] parametersTypes = definition.ParameterTypes.ToArray();

            MethodBuilder passthroughMethod = TargetType.DefineMethod
                                              (
                $"{workUnit.GetUniqueBaseMemberName()}_wrapped",
                MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                CallingConventions.Standard,
                newReturnType,
                parametersTypes
                                              );

            passthroughMethod.ApplyCustomAttributesFrom(definition, newReturnType, parametersTypes);

            return(new IntrospectiveMethodInfo
                   (
                       passthroughMethod,
                       newReturnType,
                       parametersTypes,
                       definition.MetadataType,
                       definition
                   ));
        }
Example #2
0
        /// <inheritdoc />
        public override IntrospectiveMethodInfo GeneratePassthroughDefinition(PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var  returnType = workUnit.Definition.ReturnType;
            Type newReturnType;
            var  definition = workUnit.Definition;

            if (IsSpanType(returnType))
            {
                var genericType = returnType.GenericTypeArguments[0];

                if (!genericType.IsUnmanaged())
                {
                    throw new NotSupportedException($"Method return type must be blittable.");
                }

                newReturnType = genericType.MakePointerType();
            }
            else
            {
                newReturnType = returnType;
            }

            var parametersTypes = definition.ParameterTypes.ToArray();

            for (int i = 0; i < parametersTypes.Length; ++i)
            {
                var paramType = parametersTypes[i];
                if (IsSpanType(paramType))
                {
                    var genericParam = paramType.GenericTypeArguments[0];

                    if (genericParam.IsGenericType)
                    {
                        throw new NotSupportedException("Generic type found as Span generic argument");
                    }

                    if (!genericParam.IsUnmanaged())
                    {
                        throw new NotSupportedException("Reference or value type containing references found in Span<T> or ReadOnlySpan<T> generic parameter.");
                    }

                    parametersTypes[i] = genericParam.MakePointerType(); // genercParam.MakePointerType();
                }
            }

            MethodBuilder passthroughMethod = TargetType.DefineMethod
                                              (
                $"{workUnit.GetUniqueBaseMemberName()}_wrapped",
                MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                CallingConventions.Standard,
                newReturnType,
                parametersTypes
                                              );

            passthroughMethod.ApplyCustomAttributesFrom(definition, newReturnType, parametersTypes);

            return(new IntrospectiveMethodInfo
                   (
                       passthroughMethod,
                       newReturnType,
                       parametersTypes,
                       definition.MetadataType,
                       definition
                   ));
        }