void InitMethodTable(Dictionary <Type, List <MethodInfo> > table, Type attribute, bool byRef) { foreach (MethodInfo info in this.GetType().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { if (MarshalingDescriptor.HasAttribute(info, attribute)) { ParameterInfo[] ps = info.GetParameters(); if (ps.Length == 1) { Type pt = ps[0].ParameterType; if (!byRef || byRef && pt.IsByRef && !ps[0].IsOut) { if (byRef) { pt = pt.GetElementType(); } List <MethodInfo> ms; if (!table.TryGetValue(pt, out ms)) { table[pt] = ms = new List <MethodInfo>(); } ms.Add(info); } } } } }
private void CheckPossibleValueInUnion(object value, ICustomAttributeProvider provider) { string switchExpr; if (provider == null || !MarshalingDescriptor.TryGetAttribute <string>( provider, typeof(SwitchAttribute), "expr", out switchExpr)) { throw new InvalidOperationException(String.Format( CultureInfo.InvariantCulture, "cannot find switch attribute for union '{0}'", value.GetType().Name)); } Type type = value.GetType(); var fieldsToCheck = new List <FieldInfo>(); var defaultFields = new List <FieldInfo>(); foreach (var field in type.GetFields()) { string caseExpr; if (MarshalingDescriptor.TryGetAttribute <string>(field, typeof(CaseAttribute), "expr", out caseExpr)) { IList <int?> caseValues = marshaler.EvaluateConstant(caseExpr); int switchValue = marshaler.Evaluate(switchExpr); if (caseValues.Contains(switchValue)) { fieldsToCheck.Add(field); } } else if (field.GetCustomAttributes(typeof(CaseDefaultAttribute), false).Length != 0) { defaultFields.Add(field); } } if (fieldsToCheck.Count == 0) { fieldsToCheck.AddRange(defaultFields); } foreach (var field in fieldsToCheck) { object fieldValue = field.GetValue(value); if (IsStruct(field.GetType())) { CheckPossibleValue(fieldValue, field); } else if (HasPossibleValue(field)) { CheckFieldValue(fieldValue, field); } } }
public void Initialize <T>(ref T value) { lock (messageUtilsLock) { object obj = (object)value; Type t = typeof(T); marshaler.EnterContext(); foreach (FieldInfo field in t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { Type ft = field.FieldType; if (ft.IsEnum) { bool exclusive = !MarshalingDescriptor.HasAttribute(ft, typeof(FlagsAttribute)); if (exclusive) { FieldInfo[] df = ft.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (df != null && df.Length > 0) { field.SetValue(obj, df[0].GetRawConstantValue()); } } } else if (ft.IsArray) { int size, length; marshaler.GetAdvocatedSize(new MarshalingDescriptor(ft, field), out size, out length); if (size >= 0) { if (ft.IsArray) { field.SetValue(obj, Array.CreateInstance(ft.GetElementType(), size)); } else { field.SetValue(obj, CreateSequence(ft.GetGenericArguments()[0], size)); } } } marshaler.DefineSymbol(field.Name, field.GetValue(obj)); } marshaler.ExitContext(); List <MethodInfo> ms; if (initializers.TryGetValue(t, out (ms))) { foreach (MethodInfo m in ms) { object[] args = new object[] { obj }; m.Invoke(this, args); obj = args[0]; } } value = (T)obj; } }
/// <summary> /// Create native marshaller. /// </summary> /// <param name="type">Type of struct.</param> /// <param name="switchValue">Switch attribute value if presents.</param> /// <param name="sizeValue">Size attribute value if presents.</param> /// <param name="lengthValue">Length attribute value if presents.</param> /// <param name="marshalDesccriptor">marshal descriptor</param> /// <returns>created marshaller</returns> private static Marshaler CreateNativeMarshaller( Type type, object switchValue, object sizeValue, object lengthValue, bool force32Bit, int align, out MarshalingDescriptor marshalDesccriptor ) { MarshalingConfiguration mc = NativeMarshalingConfiguration.Configuration; if (align != -1) { mc.Alignment = align; } if (force32Bit) { mc.IntPtrSize = 4; } Marshaler marshaller = new Marshaler(mc); SwitchAttribute switchAttr = null; SizeAttribute sizeAttr = null; LengthAttribute lengthAttr = null; string nameSuffix = DateTime.UtcNow.ToString("yyyyMMddHHmmss", CultureInfo.InvariantCulture); if (switchValue != null) { string switchSymbolName = "switch_" + nameSuffix; marshaller.DefineSymbol(switchSymbolName, switchValue); switchAttr = new SwitchAttribute(switchSymbolName); } if (sizeValue != null) { string sizeSymbolName = "size_" + nameSuffix; marshaller.DefineSymbol(sizeSymbolName, sizeValue); sizeAttr = new SizeAttribute(sizeSymbolName); } if (lengthValue != null) { string lengthSymbolName = "length_" + nameSuffix; marshaller.DefineSymbol(lengthSymbolName, lengthValue); lengthAttr = new LengthAttribute(lengthSymbolName); } TypeCustomAttributeProvider attrProvider = new TypeCustomAttributeProvider(switchAttr, sizeAttr, lengthAttr); marshalDesccriptor = new MarshalingDescriptor(type, attrProvider); return(marshaller); }
internal RpcParameter(ParameterInfo paramInfo, Type paramType, Type nativeType) { Type t = paramType; if (paramType.Name == "Nullable`1") { t = paramType.GetGenericArguments()[0]; } this.context = new MarshalingDescriptor(t, paramInfo); this.IsByRef = paramInfo.ParameterType.IsByRef; this.IsOut = paramInfo.IsOut; this.nativeType = nativeType; this.marshallingRegion = null; }
Type GetNativeType(ParameterInfo paramInfo, Type type) { if (type == typeof(void)) { return(type); } MarshalingDescriptor desc = new MarshalingDescriptor(type, paramInfo); Type nativeType = msr.GetNativeType(desc); if (nativeType == null) { msr.TestAssumeFail(desc, "Unsupported native type representation. (You can use [Indirect] to pass a pointer.)", paramInfo.Name, type); } return(nativeType); }
public bool CheckValueByEnum(Object value, Type type) { object obj = (object)value; Type t = type; bool exclusive = !MarshalingDescriptor.HasAttribute(t, typeof(FlagsAttribute)); if (exclusive) { try { if (!Enum.IsDefined(t, obj)) { return(false); } } catch (InvalidOperationException ex) { if (host != null) { host.Assert(false, ex.ToString()); } } } else { object x = value; foreach (object v in Enum.GetValues(t)) { x = ExcludeBits(x, v); } if (!HasNoBits(x)) { return(false); } } return(true); }
/// <summary> /// Computes the alignment of the given marshaling descriptor. /// It is the delegate to the configured type marshaler. /// </summary> /// <param name="descriptor">The marshaling descriptor.</param> /// <returns>The alignment.</returns> public int GetAlignment(MarshalingDescriptor descriptor) { ITypeMarshaler msr = GetMarshaler(descriptor); return msr.GetAlignment(this, descriptor); }
/// <summary> /// Test case assume fails with marshaling description, a given message, and additional parameters. /// </summary> /// <param name="desc">Marshaling descriptor</param> /// <param name="message">The given message</param> /// <param name="parameters">Additional parameters</param> public void TestAssumeFail(MarshalingDescriptor desc, string message, params object[] parameters) { string failedMessage = GetMessage(desc, message, parameters); if (host != null) { host.Assume(false, failedMessage); } else { Console.WriteLine(failedMessage); throw new InvalidOperationException(failedMessage); } }
internal RpcParameter(ParameterInfo paramInfo, Type paramType, Type nativeType) { Type t = paramType; if (paramType.Name == "Nullable`1") { t = paramType.GetGenericArguments()[0]; } this.context = new MarshalingDescriptor(t, paramInfo); this.IsByRef = paramInfo.ParameterType.IsByRef; this.IsOut = paramInfo.IsOut; this.nativeType = nativeType; this.marshallingRegion = null; }
/// <summary> /// Unmarshals the given value. /// It is the delegate to the configured type marshaler. /// </summary> /// <param name="descriptor">The marshaling descriptor.</param> /// <returns>The unmarshaled value.</returns> public object Unmarshal(MarshalingDescriptor descriptor) { Trace("unmarshaling {0}", descriptor); ITypeMarshaler msr = GetMarshaler(descriptor); if (msr.GetType() != typeof(BitMarshaler)) { CheckBitAlignment(); } return msr.Unmarshal(this, descriptor); }
/// <summary> /// Inherit from IEvaluationContext, currently not used in Marshaler. /// </summary> /// <param name="typeName">The custom type to be resolved</param> /// <param name="size">The actual size of the custom type</param> /// <returns>Returns true if it resolves the type successfully.</returns> public bool TryResolveCustomType(string typeName, out string size) { object type; if (customTypes.TryGetValue(typeName, out type)) { Type customType = (Type)type; MarshalingDescriptor descriptor = new MarshalingDescriptor(customType); ITypeMarshaler msr = GetMarshaler(descriptor); size = msr.GetSize(this, descriptor, null).ToString(CultureInfo.InvariantCulture); return true; } else { size = "0"; return false; } }
/// <summary> /// Marshals the given value. /// It is the delegate to the configured type marshaler. /// </summary> /// <param name="descriptor">The marshaling descriptor.</param> /// <param name="value">The value to be marshaled.</param> /// <returns></returns> public void Marshal(MarshalingDescriptor descriptor, object value) { Trace("marshaling {0}", descriptor); ITypeMarshaler msr = GetMarshaler(descriptor); if (msr.GetType() != typeof(BitMarshaler)) { CheckBitAlignment(); } msr.Marshal(this, descriptor, value); }
/// <summary> /// Marshals the given value into the specified region. /// This method enters the region, delegates to the configured type marshaler, and exits the region. /// </summary> /// <param name="descriptor">The marshaling descriptor.</param> /// <param name="customRegion">The custom region.</param> /// <param name="value">The value to be marshaled.</param> public void MarshalInto(MarshalingDescriptor descriptor, IRegion customRegion, object value) { Trace("marshaling {0}", descriptor); EnterRegion(customRegion); ITypeMarshaler msr = GetMarshaler(descriptor); msr.Marshal(this, descriptor, value); CheckBitAlignment(); ExitRegion(); }
/// <summary> /// Gets the native type of the given marshaling descriptor, if any. /// It is the delegate to the configured type marshaler. /// </summary> /// <param name="descriptor">The marshaling descriptor.</param> /// <returns>The native type.</returns> public Type GetNativeType(MarshalingDescriptor descriptor) { ITypeMarshaler msr = GetMarshaler(descriptor); return msr.GetNativeType(this, descriptor); }
/// <summary> /// Computes the size of the given marshaling descriptor and value. /// It is the delegate to the configured type marshaler. /// If the size depends on the value and the value is unknown (null), a negative value maybe returned. /// </summary> /// <param name="descriptor">The marshaling descriptor.</param> /// <param name="value">The value.</param> /// <returns>The size of the given value.</returns> public int GetSize(MarshalingDescriptor descriptor, object value) { ITypeMarshaler msr = GetMarshaler(descriptor); return msr.GetSize(this, descriptor, value); }
Type GetNativeType(ParameterInfo paramInfo, Type type) { if (type == typeof(void)) return type; MarshalingDescriptor desc = new MarshalingDescriptor(type, paramInfo); Type nativeType = msr.GetNativeType(desc); if (nativeType == null) msr.TestAssumeFail(desc, "Unsupported native type representation. (You can use [Indirect] to pass a pointer.)", paramInfo.Name, type); return nativeType; }
public void GetMultipleAdvocatedSizes(MarshalingDescriptor descriptor, out IList<int> sizes, out IList<int> lengths) { string sizeExpr; sizes = new List<int>(); lengths = new List<int>(); int size; // Evaluate static size expression if (MarshalingDescriptor.TryGetAttribute<int>(descriptor.Attributes, typeof(StaticSizeAttribute), "size", out size)) { StaticSizeMode mode; if (!MarshalingDescriptor.TryGetAttribute<StaticSizeMode>(descriptor.Attributes, typeof(StaticSizeAttribute), "mode", out mode)) throw new InvalidOperationException("expected mode field in static size attribute"); if (mode == StaticSizeMode.Bytes) { Type elementType; if (descriptor.Type.IsArray) elementType = descriptor.Type.GetElementType(); else elementType = descriptor.Type.GetGenericArguments()[0]; int s = GetSize(new MarshalingDescriptor(elementType), Activator.CreateInstance(elementType)); if (s < 0) TestAssumeFail(descriptor, "must be able to determine size of element type"); size /= s; } if (size < 0) TestAssumeFail(descriptor, "invalide static size '{0}'", size); sizes.Add(size); } // Evaluate size expression if (MarshalingDescriptor.TryGetAttribute<string>( descriptor.Attributes, typeof(SizeAttribute), "expr", out sizeExpr)) { if (sizes.Count > 0) TestAssumeFail(descriptor, "invalid combination of static with dynamic size"); IList<int?> nullableSizes = this.EvaluateSizeExpression(sizeExpr, descriptor); if (nullableSizes.Count > 0 && nullableSizes[0] == null) { nullableSizes[0] = 1; } foreach (int? value in nullableSizes) { if (value == null) { TestAssertFail(descriptor, "invalid dynamic size expression '{0}'", sizeExpr); } if (value < 0) { TestAssertFail(descriptor, "invalid dynamic size '{0}'", value); } sizes.Add((int)value); } } // Evaluate length expression if (MarshalingDescriptor.TryGetAttribute<string>( descriptor.Attributes, typeof(LengthAttribute), "expr", out sizeExpr)) { IList<int?> nullableLengths = this.EvaluateMultipleExpressions(sizeExpr); if (nullableLengths.Count != sizes.Count) { TestAssertFail(descriptor, "the number of size values in size attribute is different from the number of length values in length attribute"); } if (nullableLengths.Count > 0 && nullableLengths[0] == null) { nullableLengths[0] = 1; } for (int i = 0; i < nullableLengths.Count; i++) { if (nullableLengths[i] == null) { TestAssertFail(descriptor, "invalid length expression '{0}'", sizeExpr); } lengths.Add((int)nullableLengths[i]); if (lengths[i] < 0) TestAssertFail(descriptor, "invalid length '{0}'", lengths[i]); if (lengths[i] > sizes[i]) TestAssertFail(descriptor, "length '{0}' is greater than size '{1}'", lengths[i], sizes[i]); } } if (sizes.Count == 0) { size = 1; sizes.Add(size); lengths.Add(size); } if (lengths.Count == 0) { lengths = sizes; } }
/// <summary> /// Unmarshals the given value from the specified region. /// This method enters the region, delegates to the configured type marshaler, and exits the region. /// </summary> /// <param name="descriptor">The marshaling descriptor.</param> /// <param name="customRegion">The custom region.</param> /// <returns>The unmarshaled value.</returns> public object UnmarshalFrom(MarshalingDescriptor descriptor, IRegion customRegion) { Trace("unmarshaling {0}", descriptor); EnterRegion(customRegion); ITypeMarshaler msr = GetMarshaler(descriptor); object r = msr.Unmarshal(this, descriptor); CheckBitAlignment(); ExitRegion(); return r; }
/// <summary> /// Retrieves the advocated size and length of a marshaling descriptor by inspecting the /// attributes attached to it. /// </summary> /// <param name="descriptor">The marshaling descriptor.</param> /// <param name="size">The advocated size.</param> /// <param name="length">The advocated length.</param> public void GetAdvocatedSize(MarshalingDescriptor descriptor, out int size, out int length) { string sizeExpr; length = -1; if (MarshalingDescriptor.TryGetAttribute<int>(descriptor.Attributes, typeof(StaticSizeAttribute), "size", out size)) { StaticSizeMode mode; if (!MarshalingDescriptor.TryGetAttribute<StaticSizeMode>(descriptor.Attributes, typeof(StaticSizeAttribute), "mode", out mode)) throw new InvalidOperationException("expected mode field in static size attribute"); if (mode == StaticSizeMode.Bytes) { Type elementType; if (descriptor.Type.IsArray) elementType = descriptor.Type.GetElementType(); else elementType = descriptor.Type.GetGenericArguments()[0]; int s = GetSize(new MarshalingDescriptor(elementType), Activator.CreateInstance(elementType)); if (s < 0) TestAssumeFail(descriptor, "must be able to determine size of element type"); size /= s; } if (size < 0) TestAssumeFail(descriptor, "invalide static size '{0}'", size); } else size = -1; if (MarshalingDescriptor.TryGetAttribute<string>( descriptor.Attributes, typeof(SizeAttribute), "expr", out sizeExpr)) { if (size >= 0) TestAssumeFail(descriptor, "invalid combination of static with dynamic size"); IList<int?> sizes = this.EvaluateSizeExpression(sizeExpr, descriptor); if (sizes.Count != 1) { TestAssumeFail(descriptor, "size expression is invalid (expect one size value in the expression)."); } if (sizes[0] == null) { TestAssumeFail(descriptor, "evaluating size expression failed"); } size = sizes[0].Value; if (size < 0) TestAssertFail(descriptor, "invalid dynamic size '{0}'", size); } if (MarshalingDescriptor.TryGetAttribute<string>( descriptor.Attributes, typeof(LengthAttribute), "expr", out sizeExpr)) { length = this.Evaluate(sizeExpr); if (length < 0) TestAssertFail(descriptor, "invalid length '{0}'", length); } if (size < 0) size = length; if (size < 0) size = 1; if (length < 0) length = size; if (length > size) TestAssertFail(descriptor, "length '{0}' greater than size '{1}'", length, size); }
/// <summary> /// Defines symbols /// </summary> /// <param name="fields">The fields corresponding to the symbols</param> /// <param name="value">The values corresponding to the symbols</param> public void DefineSymbols(FieldInfo[] fields, object value) { if (fields == null) { throw new ArgumentNullException("fields"); } foreach (FieldInfo field in fields) { MarshalingDescriptor fdesc = new MarshalingDescriptor(field.FieldType, field); object fieldValue = field.GetValue(value); Type nt; try { nt = GetNativeType(fdesc); } catch (InvalidOperationException) // some types does not have native type. { nt = null; } if (nt == typeof(IntPtr)) { DefinePointerSymbol(field.Name, fieldValue); } else { DefineSymbol(field.Name, fieldValue); } } }
IList<int?> EvaluateSizeExpression(string sizeExpr, MarshalingDescriptor descriptor) { IList<int?> nullableSizes = new List<int?>(); // Do custom calculation when the first char is '@' if (sizeExpr.StartsWith("@", StringComparison.OrdinalIgnoreCase)) { if (descriptor.ContainerType == null) { TestAssumeFail(descriptor, "cannot find the type which contains custom calculation method"); } if (sizeExpr.Length < 2) { TestAssumeFail(descriptor, "cannot find method name in the size expression"); } // remove the first char '@' to get method name. string methodName = sizeExpr.Substring(1); MethodInfo method = descriptor.ContainerType.GetMethod( methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { TestAssumeFail(descriptor, "cannot find custom calculation method"); } // Check the method signature. ParameterInfo[] paramInfos = method.GetParameters(); if (paramInfos.Length == 1 && paramInfos[0].ParameterType == typeof(IEvaluationContext) && method.ReturnParameter.ParameterType == typeof(int)) { int customSize = (int)method.Invoke(null, new object[] { this }); nullableSizes.Add(customSize); } else { TestAssumeFail(descriptor, "the custom calculation method signature is invalid"); } } else { nullableSizes = this.EvaluateMultipleExpressions(sizeExpr); } return nullableSizes; }
static string GetMessage(MarshalingDescriptor desc, string message, params object[] parameters) { string failMessage = parameters.Length > 0 ? String.Format(CultureInfo.InvariantCulture, message, parameters) : message; if (desc.Type != null) { failMessage = string.Format(CultureInfo.InvariantCulture, "while processing '{0}': {1}", desc, failMessage); } return failMessage; }
/// <summary> /// Returns the type marshaler determined by the marshaling configuration. /// </summary> /// <param name="descriptor">The marshaling descriptor.</param> /// <returns>The type marshaler.</returns> public ITypeMarshaler GetMarshaler(MarshalingDescriptor descriptor) { return config.GetMarshaler(this, descriptor); }
/// <summary> /// Test case assert fails with marshaling description, a given message, and additional parameters. /// </summary> /// <param name="desc">Marshaling descriptor</param> /// <param name="message">The given message</param> /// <param name="parameters">Additional parameters</param> public void TestAssertFail(MarshalingDescriptor desc, string message, params object[] parameters) { if (host != null) { host.Assert(false, GetMessage(desc, message, parameters)); } else { Console.WriteLine("FAIL: " + message); throw new InvalidOperationException(message); } }