/// <summary> /// Initializes the array as a <see cref="UnmanagedType.ByValArray"/>. /// </summary> private void InitializeAsByValArray(NativeTypeDesc desc) { Debug.Assert(this.indirections == 0); this.arrayKind = ArrayKind.ByValArray; // const size must be specified and >0 if (desc.MarshalAs == null || desc.MarshalAs.SizeConst <= 0) { Log.Add(Errors.ERROR_ByValArrayInvalidLength); this.length = 1; } else { // no need to output any INFO as this number will be between brackets in the code this.length = desc.MarshalAs.SizeConst; } UnmanagedType element_unmng_type = (desc.MarshalAs == null ? (UnmanagedType)0 : desc.MarshalAs.ArraySubType); if (element_unmng_type == (UnmanagedType)80) { element_unmng_type = (UnmanagedType)0; } // determine the element type this.elementType = NativeType.FromClrArrayElement(desc.Type, element_unmng_type, desc.Flags); }
/// <summary> /// Initializes the array as a <see cref="UnmanagedType.LPArray"/>. /// </summary> private void InitializeAsNativeArray(NativeTypeDesc desc) { this.arrayKind = ArrayKind.NativeArray; if (desc.IsByRefParam) { // SizeConst and SizeParamIndex are not allowed for byref if (HasSizeConst(desc) || HasSizeParamIndex(desc)) { Log.Add(Errors.ERROR_ArraySizeNotAllowedForByref); } } else if (!desc.IsCallbackParam) { // when marshaling from managed to native, size is implicit (warn if given explicitly) if (HasSizeConst(desc) || HasSizeParamIndex(desc)) { Log.Add(Errors.WARN_ArraySizesIgnored); } else { Log.Add(Errors.INFO_ArraySizeDeterminedDynamically); } } else { // when marshaling from native to managed, size must be given, otherwise it's 1 if (HasSizeParamIndex(desc)) { Debug.Assert(desc.ParameterInfo != null); ParameterInfo[] parameters = ((MethodBase)desc.ParameterInfo.Member).GetParameters(); int param_index = desc.MarshalAs.SizeParamIndex; if (param_index < 0 || param_index >= parameters.Length) { // index OOR (error) Log.Add(Errors.ERROR_ArraySizeParamIndexOutOfRange, param_index); } else if (!TypeAllowedInSizeParam(parameters[param_index].ParameterType)) { // index refers to bad param (error) Log.Add(Errors.ERROR_ArraySizeParamWrongType, parameters[param_index].ParameterType); } else { // determine parameter name string param_name = parameters[param_index].Name; if (String.IsNullOrEmpty(param_name)) { param_name = String.Format(Resources.Number, param_index + 1); } if (desc.MarshalAs.SizeConst > 0) { // size = [param_at_the_index] + size_const; Log.Add(Errors.INFO_ArraySizeIsByParameterPlusConstant, param_name, desc.MarshalAs.SizeConst); } else { // size = [param_at_the_index] Log.Add(Errors.INFO_ArraySizeIsByParameter, param_name); } } } else if (HasSizeConst(desc)) { // size = size_const Log.Add(Errors.INFO_ArraySizeIsConstant, desc.MarshalAs.SizeConst); } else { // size = 1 (warn) Log.Add(Errors.WARN_ArraySizeDefaultsToOne); } } UnmanagedType element_unmng_type = (desc.MarshalAs == null ? (UnmanagedType)0 : desc.MarshalAs.ArraySubType); if (element_unmng_type == (UnmanagedType)80) { element_unmng_type = (UnmanagedType)0; } // determine the element type this.elementType = NativeType.FromClrArrayElement(desc.Type, element_unmng_type, desc.Flags); ExplainMemoryManagement(desc, Resources._Array); }
/// <summary> /// Initializes the array as a <see cref="UnmanagedType.SafeArray"/>. /// </summary> private void InitializeAsSafeArray(NativeTypeDesc desc) { this.arrayKind = ArrayKind.SafeArray; Type array_mng_type = desc.Type; VarEnum sub_type = VarEnum.VT_EMPTY; if (desc.MarshalAs != null && desc.MarshalAs.SafeArraySubType != VarEnum.VT_EMPTY) { sub_type = desc.MarshalAs.SafeArraySubType; } else { // the unmanaged type may also be specified statically using one of the wrapper classes if (array_mng_type == typeof(UnknownWrapper[])) { array_mng_type = typeof(object[]); sub_type = VarEnum.VT_UNKNOWN; } else if (array_mng_type == typeof(DispatchWrapper[])) { array_mng_type = typeof(object[]); sub_type = VarEnum.VT_DISPATCH; } else if (array_mng_type == typeof(ErrorWrapper[])) { array_mng_type = typeof(int[]); sub_type = VarEnum.VT_ERROR; } else if (array_mng_type == typeof(CurrencyWrapper[])) { array_mng_type = typeof(Decimal[]); sub_type = VarEnum.VT_CY; } else if (array_mng_type == typeof(BStrWrapper[])) { array_mng_type = typeof(string[]); sub_type = VarEnum.VT_BSTR; } } // convert the SafeArraySubType to UnmanagedType UnmanagedType element_unmng_type = Utility.VarEnumToUnmanagedType(sub_type); // determine the element type // (this will have no effect on the C++ signature but we will check it and add it to log) this.elementType = NativeType.FromClrArrayElement( array_mng_type, element_unmng_type, (desc.Flags & ~MarshalFlags.ByRefParam) | MarshalFlags.ComInterop); if (sub_type == VarEnum.VT_EMPTY) { sub_type = Utility.TypeToVarEnum(array_mng_type.GetElementType()); } if (!elementType.IsInvalid) { if (array_mng_type != typeof(System.Array) || sub_type != VarEnum.VT_EMPTY) { // log the element native type Log.Add(Errors.INFO_SafeArrayWillMarshalAs, sub_type.ToString()); } } // also include the *Wrapper hint if applicable if (desc.Type == typeof(object[]) && (sub_type == VarEnum.VT_EMPTY || sub_type == VarEnum.VT_VARIANT)) { Log.Add(Errors.INFO_SafeArrayOfVariantsWrapperUse); } ExplainMemoryManagement(desc, Resources._SafeArray); }