public CsParameter Create()

in SharpGen/Transform/MarshalledElementFactory.cs [181:283]


        public CsParameter Create(CppParameter cppParameter, string name)
        {
            CsParameter param = new(ioc, cppParameter, name);
            CreateCore(param);

            if (cppParameter.IsAttributeRuleRedundant)
                Logger.Message("Parameter [{0}] has redundant attribute rule specification", cppParameter.FullName);

            static bool HasFlag(ParamAttribute value, ParamAttribute flag) => (value & flag) == flag;

            // --------------------------------------------------------------------------------
            // Pointer - Handle special cases
            // --------------------------------------------------------------------------------
            if (param.HasPointer)
            {
                var paramRule = cppParameter.Rule;
                var numIndirections = cppParameter.Pointer.Count(static p => p is '*' or '&');
                bool isBuffer, isIn, isInOut, isOut;

                {
                    var cppAttribute = cppParameter.Attribute;

                    // Force Interface** to be ParamAttribute.Out
                    if (param.PublicType is CsInterface && cppAttribute == ParamAttribute.In && numIndirections == 2)
                        cppAttribute = ParamAttribute.Out;

                    isBuffer = HasFlag(cppAttribute, ParamAttribute.Buffer);
                    isIn = HasFlag(cppAttribute, ParamAttribute.In);
                    isInOut = HasFlag(cppAttribute, ParamAttribute.InOut);
                    isOut = HasFlag(cppAttribute, ParamAttribute.Out);
                }

                // Either In, InOut or Out is set
                Debug.Assert((isIn ? 1 : 0) + (isInOut ? 1 : 0) + (isOut ? 1 : 0) == 1);

                // --------------------------------------------------------------------------------
                // Handling Parameter Interface
                // --------------------------------------------------------------------------------
                if (param.PublicType is CsInterface)
                {
                    // Simplify logic by assuming interface instance pointer is the interface itself.
                    --numIndirections;

                    if (isOut)
                        param.Attribute = CsParameterAttribute.Out;
                }
                else if (isIn)
                {
                    var publicType = param.PublicType;

                    param.Attribute = publicType is CsFundamentalType {IsPointerSize: true}
                                   || publicType.IsWellKnownType(GlobalNamespace, WellKnownName.FunctionCallback)
                                          ? CsParameterAttribute.In
                                          : CsParameterAttribute.RefIn;
                }
                else if (isInOut)
                {
                    if (param.IsOptional)
                    {
                        param.SetPublicResetMarshalType(PointerType(paramRule));
                        param.Attribute = CsParameterAttribute.In;
                    }
                    else
                    {
                        param.Attribute = CsParameterAttribute.Ref;
                    }
                }
                else if (isOut)
                {
                    param.Attribute = CsParameterAttribute.Out;
                }

                switch (param.PublicType)
                {
                    // Handle void* with Buffer attribute
                    case CsFundamentalType {IsUntypedPointer: true} when isBuffer:
                        param.Attribute = CsParameterAttribute.In;
                        param.IsArray = false;
                        break;
                    // Handle strings with Out attribute
                    case CsFundamentalType {IsString: true} when isOut:
                        param.Attribute = CsParameterAttribute.In;
                        param.IsArray = false;
                        param.SetPublicResetMarshalType(TypeRegistry.IntPtr);
                        break;
                    // There's no way to know how to deallocate native-allocated memory correctly
                    // since we don't know what allocator the native memory uses,
                    // so we treat any extra pointer indirections as IntPtr
                    case not CsFundamentalType {IsUntypedPointer: true} when numIndirections > 1:
                        param.IsArray = false;
                        param.SetPublicResetMarshalType(TypeRegistry.IntPtr);
                        break;
                }
            }

            if (param.Relations.OfType<StructSizeRelation>().Any())
                Logger.Error(
                    LoggingCodes.InvalidRelation,
                    $"Parameter [{cppParameter}] marked with a struct-size relationship"
                );

            return param;
        }