2 Copyright (C) 2008-2012 Jeroen Frijters
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
25 using System.Collections.Generic;
26 using System.Runtime.InteropServices;
28 using IKVM.Reflection.Emit;
29 using IKVM.Reflection.Reader;
30 using IKVM.Reflection.Writer;
31 using IKVM.Reflection.Metadata;
33 namespace IKVM.Reflection
35 public struct FieldMarshal
37 private const UnmanagedType NATIVE_TYPE_MAX = (UnmanagedType)0x50;
38 public UnmanagedType UnmanagedType;
39 public UnmanagedType? ArraySubType;
40 public short? SizeParamIndex;
41 public int? SizeConst;
42 public VarEnum? SafeArraySubType;
43 public Type SafeArrayUserDefinedSubType;
44 public int? IidParameterIndex;
45 public string MarshalType;
46 public string MarshalCookie;
47 public Type MarshalTypeRef;
49 internal static bool ReadFieldMarshal(Module module, int token, out FieldMarshal fm)
51 fm = new FieldMarshal();
52 foreach (int i in module.FieldMarshal.Filter(token))
54 ByteReader blob = module.GetBlob(module.FieldMarshal.records[i].NativeType);
55 fm.UnmanagedType = (UnmanagedType)blob.ReadCompressedInt();
56 if (fm.UnmanagedType == UnmanagedType.LPArray)
58 fm.ArraySubType = (UnmanagedType)blob.ReadCompressedInt();
59 if (fm.ArraySubType == NATIVE_TYPE_MAX)
61 fm.ArraySubType = null;
65 fm.SizeParamIndex = (short)blob.ReadCompressedInt();
68 fm.SizeConst = blob.ReadCompressedInt();
69 if (blob.Length != 0 && blob.ReadCompressedInt() == 0)
71 fm.SizeParamIndex = null;
76 else if (fm.UnmanagedType == UnmanagedType.SafeArray)
80 fm.SafeArraySubType = (VarEnum)blob.ReadCompressedInt();
83 fm.SafeArrayUserDefinedSubType = ReadType(module, blob);
87 else if (fm.UnmanagedType == UnmanagedType.ByValArray)
89 fm.SizeConst = blob.ReadCompressedInt();
92 fm.ArraySubType = (UnmanagedType)blob.ReadCompressedInt();
95 else if (fm.UnmanagedType == UnmanagedType.ByValTStr)
97 fm.SizeConst = blob.ReadCompressedInt();
99 else if (fm.UnmanagedType == UnmanagedType.Interface
100 || fm.UnmanagedType == UnmanagedType.IDispatch
101 || fm.UnmanagedType == UnmanagedType.IUnknown)
103 if (blob.Length != 0)
105 fm.IidParameterIndex = blob.ReadCompressedInt();
108 else if (fm.UnmanagedType == UnmanagedType.CustomMarshaler)
110 blob.ReadCompressedInt();
111 blob.ReadCompressedInt();
112 fm.MarshalType = ReadString(blob);
113 fm.MarshalCookie = ReadString(blob);
115 TypeNameParser parser = TypeNameParser.Parse(fm.MarshalType, false);
118 fm.MarshalTypeRef = parser.GetType(module.universe, module.Assembly, false, fm.MarshalType, false, false);
126 internal static void SetMarshalAsAttribute(ModuleBuilder module, int token, CustomAttributeBuilder attribute)
128 attribute = attribute.DecodeBlob(module.Assembly);
129 FieldMarshalTable.Record rec = new FieldMarshalTable.Record();
131 rec.NativeType = WriteMarshallingDescriptor(module, attribute);
132 module.FieldMarshal.AddRecord(rec);
135 private static int WriteMarshallingDescriptor(ModuleBuilder module, CustomAttributeBuilder attribute)
137 UnmanagedType unmanagedType;
138 object val = attribute.GetConstructorArgument(0);
141 unmanagedType = (UnmanagedType)(short)val;
145 unmanagedType = (UnmanagedType)(int)val;
149 unmanagedType = (UnmanagedType)val;
152 ByteBuffer bb = new ByteBuffer(5);
153 bb.WriteCompressedInt((int)unmanagedType);
155 if (unmanagedType == UnmanagedType.LPArray)
157 UnmanagedType arraySubType = attribute.GetFieldValue<UnmanagedType>("ArraySubType") ?? NATIVE_TYPE_MAX;
158 bb.WriteCompressedInt((int)arraySubType);
159 int? sizeParamIndex = attribute.GetFieldValue<short>("SizeParamIndex");
160 int? sizeConst = attribute.GetFieldValue<int>("SizeConst");
161 if (sizeParamIndex != null)
163 bb.WriteCompressedInt(sizeParamIndex.Value);
164 if (sizeConst != null)
166 bb.WriteCompressedInt(sizeConst.Value);
167 bb.WriteCompressedInt(1); // flag that says that SizeParamIndex was specified
170 else if (sizeConst != null)
172 bb.WriteCompressedInt(0); // SizeParamIndex
173 bb.WriteCompressedInt(sizeConst.Value);
174 bb.WriteCompressedInt(0); // flag that says that SizeParamIndex was not specified
177 else if (unmanagedType == UnmanagedType.SafeArray)
179 VarEnum? safeArraySubType = attribute.GetFieldValue<VarEnum>("SafeArraySubType");
180 if (safeArraySubType != null)
182 bb.WriteCompressedInt((int)safeArraySubType);
183 Type safeArrayUserDefinedSubType = (Type)attribute.GetFieldValue("SafeArrayUserDefinedSubType");
184 if (safeArrayUserDefinedSubType != null)
186 WriteType(module, bb, safeArrayUserDefinedSubType);
190 else if (unmanagedType == UnmanagedType.ByValArray)
192 bb.WriteCompressedInt(attribute.GetFieldValue<int>("SizeConst") ?? 1);
193 UnmanagedType? arraySubType = attribute.GetFieldValue<UnmanagedType>("ArraySubType");
194 if (arraySubType != null)
196 bb.WriteCompressedInt((int)arraySubType);
199 else if (unmanagedType == UnmanagedType.ByValTStr)
201 bb.WriteCompressedInt(attribute.GetFieldValue<int>("SizeConst").Value);
203 else if (unmanagedType == UnmanagedType.Interface
204 || unmanagedType == UnmanagedType.IDispatch
205 || unmanagedType == UnmanagedType.IUnknown)
207 int? iidParameterIndex = attribute.GetFieldValue<int>("IidParameterIndex");
208 if (iidParameterIndex != null)
210 bb.WriteCompressedInt(iidParameterIndex.Value);
213 else if (unmanagedType == UnmanagedType.CustomMarshaler)
215 bb.WriteCompressedInt(0);
216 bb.WriteCompressedInt(0);
217 string marshalType = (string)attribute.GetFieldValue("MarshalType");
218 if (marshalType != null)
220 WriteString(bb, marshalType);
224 WriteType(module, bb, (Type)attribute.GetFieldValue("MarshalTypeRef"));
226 WriteString(bb, (string)attribute.GetFieldValue("MarshalCookie") ?? "");
229 return module.Blobs.Add(bb);
232 private static Type ReadType(Module module, ByteReader br)
234 string str = ReadString(br);
239 return module.Assembly.GetType(str) ?? module.universe.GetType(str, true);
242 private static void WriteType(Module module, ByteBuffer bb, Type type)
244 WriteString(bb, type.Assembly == module.Assembly ? type.FullName : type.AssemblyQualifiedName);
247 private static string ReadString(ByteReader br)
249 return Encoding.UTF8.GetString(br.ReadBytes(br.ReadCompressedInt()));
252 private static void WriteString(ByteBuffer bb, string str)
254 byte[] buf = Encoding.UTF8.GetBytes(str);
255 bb.WriteCompressedInt(buf.Length);