25using System.Reflection.Metadata;
26using System.Reflection.Metadata.Ecma335;
27using System.Runtime.InteropServices;
38 internal struct FieldMarshal
41 const UnmanagedType UnmanagedType_CustomMarshaler = (UnmanagedType)0x2c;
42 const UnmanagedType NATIVE_TYPE_MAX = (UnmanagedType)0x50;
44 public UnmanagedType UnmanagedType;
45 public UnmanagedType? ArraySubType;
46 public short? SizeParamIndex;
47 public int? SizeConst;
48 public VarEnum? SafeArraySubType;
49 public Type SafeArrayUserDefinedSubType;
50 public int? IidParameterIndex;
51 public string MarshalType;
52 public string MarshalCookie;
53 public Type MarshalTypeRef;
55 internal static bool ReadFieldMarshal(
Module module,
int token, out FieldMarshal fm)
57 fm =
new FieldMarshal();
59 foreach (var i
in module.FieldMarshalTable.Filter(token))
61 var blob = module.GetBlobReader(module.FieldMarshalTable.records[i].NativeType);
63 fm.UnmanagedType = (UnmanagedType)blob.ReadCompressedUInt();
64 switch (fm.UnmanagedType)
66 case UnmanagedType.LPArray:
67 fm.ArraySubType = (UnmanagedType)blob.ReadCompressedUInt();
68 if (fm.ArraySubType == NATIVE_TYPE_MAX)
69 fm.ArraySubType =
null;
73 fm.SizeParamIndex = (short)blob.ReadCompressedUInt();
76 fm.SizeConst = blob.ReadCompressedUInt();
77 if (blob.Length != 0 && blob.ReadCompressedUInt() == 0)
78 fm.SizeParamIndex =
null;
82 case UnmanagedType.SafeArray:
85 fm.SafeArraySubType = (VarEnum)blob.ReadCompressedUInt();
87 fm.SafeArrayUserDefinedSubType = ReadType(module, blob);
90 case UnmanagedType.ByValArray:
91 fm.SizeConst = blob.ReadCompressedUInt();
93 fm.ArraySubType = (UnmanagedType)blob.ReadCompressedUInt();
95 case UnmanagedType.ByValTStr:
96 fm.SizeConst = blob.ReadCompressedUInt();
98 case UnmanagedType.Interface:
99 case UnmanagedType.IDispatch:
100 case UnmanagedType.IUnknown:
101 if (blob.Length != 0)
102 fm.IidParameterIndex = blob.ReadCompressedUInt();
104 case UnmanagedType_CustomMarshaler:
106 blob.ReadCompressedUInt();
107 blob.ReadCompressedUInt();
108 fm.MarshalType = ReadString(blob);
109 fm.MarshalCookie = ReadString(blob);
113 fm.MarshalTypeRef = parser.GetType(module.Universe, module,
false, fm.MarshalType,
false,
false);
124 internal static void SetMarshalAsAttribute(ModuleBuilder module,
int token, CustomAttributeBuilder attribute)
126 attribute = attribute.DecodeBlob(module.Assembly);
129 rec.NativeType = WriteMarshallingDescriptor(module, attribute);
130 module.FieldMarshalTable.AddRecord(rec);
133 static BlobHandle WriteMarshallingDescriptor(ModuleBuilder module, CustomAttributeBuilder attribute)
135 var val = attribute.GetConstructorArgument(0);
136 var unmanagedType = val
switch
138 short s => (UnmanagedType)s,
139 int i => (UnmanagedType)i,
140 _ => (UnmanagedType)val,
144 bb.WriteCompressedUInt((
int)unmanagedType);
146 switch (unmanagedType)
148 case UnmanagedType.LPArray:
150 var arraySubType = attribute.GetFieldValue<UnmanagedType>(
"ArraySubType") ?? NATIVE_TYPE_MAX;
151 bb.WriteCompressedUInt((
int)arraySubType);
153 var sizeParamIndex = attribute.GetFieldValue<
short>(
"SizeParamIndex");
154 var sizeConst = attribute.GetFieldValue<
int>(
"SizeConst");
155 if (sizeParamIndex !=
null)
157 bb.WriteCompressedUInt(sizeParamIndex.Value);
158 if (sizeConst !=
null)
160 bb.WriteCompressedUInt(sizeConst.Value);
161 bb.WriteCompressedUInt(1);
164 else if (sizeConst !=
null)
166 bb.WriteCompressedUInt(0);
167 bb.WriteCompressedUInt(sizeConst.Value);
168 bb.WriteCompressedUInt(0);
173 case UnmanagedType.SafeArray:
175 var safeArraySubType = attribute.GetFieldValue<VarEnum>(
"SafeArraySubType");
176 if (safeArraySubType !=
null)
178 bb.WriteCompressedUInt((
int)safeArraySubType);
179 var safeArrayUserDefinedSubType = (
Type)attribute.GetFieldValue(
"SafeArrayUserDefinedSubType");
180 if (safeArrayUserDefinedSubType !=
null)
181 WriteType(module, bb, safeArrayUserDefinedSubType);
186 case UnmanagedType.ByValArray:
188 bb.WriteCompressedUInt(attribute.GetFieldValue<
int>(
"SizeConst") ?? 1);
189 var arraySubType = attribute.GetFieldValue<UnmanagedType>(
"ArraySubType");
190 if (arraySubType !=
null)
191 bb.WriteCompressedUInt((
int)arraySubType);
195 case UnmanagedType.ByValTStr:
196 bb.WriteCompressedUInt(attribute.GetFieldValue<
int>(
"SizeConst").Value);
198 case UnmanagedType.Interface:
199 case UnmanagedType.IDispatch:
200 case UnmanagedType.IUnknown:
202 var iidParameterIndex = attribute.GetFieldValue<
int>(
"IidParameterIndex");
203 if (iidParameterIndex !=
null)
204 bb.WriteCompressedUInt(iidParameterIndex.Value);
208 case UnmanagedType_CustomMarshaler:
210 bb.WriteCompressedUInt(0);
211 bb.WriteCompressedUInt(0);
212 var marshalType = (string)attribute.GetFieldValue(
"MarshalType");
213 if (marshalType !=
null)
214 WriteString(bb, marshalType);
216 WriteType(module, bb, (
Type)attribute.GetFieldValue(
"MarshalTypeRef"));
218 WriteString(bb, (
string)attribute.GetFieldValue(
"MarshalCookie") ??
"");
223 return module.GetOrAddBlob(bb.ToArray());
228 var str = ReadString(br);
232 return module.Assembly.GetType(str) ?? module.Universe.GetType(str,
true);
237 WriteString(bb, type.Assembly == module.Assembly ? type.FullName : type.AssemblyQualifiedName);
242 return Encoding.UTF8.GetString(br.ReadBytes(br.ReadCompressedUInt()));
245 static void WriteString(
ByteBuffer bb,
string str)
247 var buf = Encoding.UTF8.GetBytes(str);
248 bb.WriteCompressedUInt(buf.Length);
IKVM.Reflection.Module Module
IKVM.Reflection.Type Type