PageRenderTime 47ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/Languages/IronPython/IronPython.Modules/_ctypes/UnionType.cs

http://github.com/IronLanguages/main
C# | 210 lines | 152 code | 35 blank | 23 comment | 20 complexity | dac43e4b44fa1d35eea089d2a0f1334e MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if FEATURE_NATIVE
  16. using System;
  17. using System.Collections;
  18. using System.Collections.Generic;
  19. using System.Reflection.Emit;
  20. using Microsoft.Scripting;
  21. using Microsoft.Scripting.Runtime;
  22. using IronPython.Runtime;
  23. using IronPython.Runtime.Operations;
  24. using IronPython.Runtime.Types;
  25. namespace IronPython.Modules {
  26. /// <summary>
  27. /// Provides support for interop with native code from Python code.
  28. /// </summary>
  29. public static partial class CTypes {
  30. /// <summary>
  31. /// The meta class for ctypes unions.
  32. /// </summary>
  33. [PythonType, PythonHidden]
  34. public class UnionType : PythonType, INativeType {
  35. internal Field[] _fields;
  36. private int _size, _alignment;
  37. public UnionType(CodeContext/*!*/ context, string name, PythonTuple bases, PythonDictionary members)
  38. : base(context, name, bases, members) {
  39. object fields;
  40. if (members.TryGetValue("_fields_", out fields)) {
  41. SetFields(fields);
  42. }
  43. }
  44. public new void __setattr__(CodeContext/*!*/ context, string name, object value) {
  45. if (name == "_fields_") {
  46. lock (this) {
  47. if (_fields != null) {
  48. throw PythonOps.AttributeError("_fields_ is final");
  49. }
  50. SetFields(value);
  51. }
  52. }
  53. base.__setattr__(context, name, value);
  54. }
  55. private UnionType(Type underlyingSystemType)
  56. : base(underlyingSystemType) {
  57. }
  58. /// <summary>
  59. /// Converts an object into a function call parameter.
  60. /// </summary>
  61. public object from_param(object obj) {
  62. return null;
  63. }
  64. internal static PythonType MakeSystemType(Type underlyingSystemType) {
  65. return PythonType.SetPythonType(underlyingSystemType, new UnionType(underlyingSystemType));
  66. }
  67. public static ArrayType/*!*/ operator *(UnionType type, int count) {
  68. return MakeArrayType(type, count);
  69. }
  70. public static ArrayType/*!*/ operator *(int count, UnionType type) {
  71. return MakeArrayType(type, count);
  72. }
  73. #region INativeType Members
  74. int INativeType.Size {
  75. get {
  76. return _size;
  77. }
  78. }
  79. int INativeType.Alignment {
  80. get {
  81. return _alignment;
  82. }
  83. }
  84. object INativeType.GetValue(MemoryHolder owner, object readingFrom, int offset, bool raw) {
  85. _Union res = (_Union)CreateInstance(this.Context.SharedContext);
  86. res._memHolder = owner.GetSubBlock(offset);
  87. return res;
  88. }
  89. object INativeType.SetValue(MemoryHolder address, int offset, object value) {
  90. IList<object> init = value as IList<object>;
  91. if (init != null) {
  92. if (init.Count > _fields.Length) {
  93. throw PythonOps.TypeError("too many initializers");
  94. }
  95. for (int i = 0; i < init.Count; i++) {
  96. _fields[i].SetValue(address, offset, init[i]);
  97. }
  98. } else {
  99. CData data = value as CData;
  100. if (data != null) {
  101. data._memHolder.CopyTo(address, offset, data.Size);
  102. return data._memHolder.EnsureObjects();
  103. } else {
  104. throw new NotImplementedException("Union set value");
  105. }
  106. }
  107. return null;
  108. }
  109. Type INativeType.GetNativeType() {
  110. return GetMarshalTypeFromSize(_size);
  111. }
  112. MarshalCleanup INativeType.EmitMarshalling(ILGenerator/*!*/ method, LocalOrArg argIndex, List<object>/*!*/ constantPool, int constantPoolArgument) {
  113. Type argumentType = argIndex.Type;
  114. argIndex.Emit(method);
  115. if (argumentType.IsValueType) {
  116. method.Emit(OpCodes.Box, argumentType);
  117. }
  118. constantPool.Add(this);
  119. method.Emit(OpCodes.Ldarg, constantPoolArgument);
  120. method.Emit(OpCodes.Ldc_I4, constantPool.Count - 1);
  121. method.Emit(OpCodes.Ldelem_Ref);
  122. method.Emit(OpCodes.Call, typeof(ModuleOps).GetMethod("CheckCDataType"));
  123. method.Emit(OpCodes.Call, typeof(CData).GetMethod("get_UnsafeAddress"));
  124. method.Emit(OpCodes.Ldobj, ((INativeType)this).GetNativeType());
  125. return null;
  126. }
  127. Type/*!*/ INativeType.GetPythonType() {
  128. return typeof(object);
  129. }
  130. void INativeType.EmitReverseMarshalling(ILGenerator method, LocalOrArg value, List<object> constantPool, int constantPoolArgument) {
  131. value.Emit(method);
  132. EmitCDataCreation(this, method, constantPool, constantPoolArgument);
  133. }
  134. string INativeType.TypeFormat {
  135. get {
  136. return "B";
  137. }
  138. }
  139. #endregion
  140. private void SetFields(object fields) {
  141. lock (this) {
  142. IList<object> list = GetFieldsList(fields);
  143. IList<object> anonFields = StructType.GetAnonymousFields(this);
  144. int size = 0, alignment = 1;
  145. List<Field> allFields = new List<Field>();//GetBaseSizeAlignmentAndFields(out size, out alignment);
  146. int? bitCount;
  147. for (int fieldIndex = 0; fieldIndex < list.Count; fieldIndex++) {
  148. object o = list[fieldIndex];
  149. string fieldName;
  150. INativeType cdata;
  151. GetFieldInfo(this, o, out fieldName, out cdata, out bitCount);
  152. alignment = Math.Max(alignment, cdata.Alignment);
  153. size = Math.Max(size, cdata.Size);
  154. Field newField = new Field(fieldName, cdata, 0, allFields.Count);
  155. allFields.Add(newField);
  156. AddSlot(fieldName, newField);
  157. if (anonFields != null && anonFields.Contains(fieldName)) {
  158. StructType.AddAnonymousFields(this, allFields, cdata, newField);
  159. }
  160. }
  161. StructType.CheckAnonymousFields(allFields, anonFields);
  162. _fields = allFields.ToArray();
  163. _size = PythonStruct.Align(size, alignment);
  164. _alignment = alignment;
  165. }
  166. }
  167. internal void EnsureFinal() {
  168. if (_fields == null) {
  169. SetFields(PythonTuple.EMPTY);
  170. }
  171. }
  172. }
  173. }
  174. }
  175. #endif