Implementing UnmanagedMarshal.DefineCustom()

Marcus <[email protected]>
Newsgroups gmane.comp.gnu.dotgnu.developer
Message-ID <[email protected]>
I chatted with Rhys yesterday about adding a non-MS extension to the 
UnmanagedMarshal class (in System.Reflection.Emit). The method would permit a 
specifying a custom marshaler for a parameter in methods that are defined at 
runtime via S.R.E.

The modifications to UnmanagedMarshal are the addition or two private string 
fields, marshalCookie and marshalType, the DefineCustom method itself, and an 
addition case to the switch statement in ToBytes().

I'm not sure where to go from here, but I'm attaching a patch to this message 
for people to look at.

Marcus
UnmanagedMarshal.patch (text/x-diff, 2.4 KB)
Index: UnmanagedMarshal.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/runtime/System/Reflection/Emit/UnmanagedMarshal.cs,v
retrieving revision 1.5
diff -u -p -u -w -r1.5 UnmanagedMarshal.cs
--- UnmanagedMarshal.cs	8 Aug 2004 07:47:40 -0000	1.5
+++ UnmanagedMarshal.cs	9 Aug 2004 06:16:19 -0000
@@ -28,6 +28,7 @@ namespace System.Reflection.Emit
 #if CONFIG_REFLECTION_EMIT
 
 using System;
+using System.Text;
 using System.Runtime.InteropServices;
 
 public sealed class UnmanagedMarshal
@@ -36,6 +37,9 @@ public sealed class UnmanagedMarshal
 	private UnmanagedType type;
 	private UnmanagedType baseType;
 	private int elemCount;
+	private string marshalCookie;
+	private string marshalType;
+
 
 	// Constructor.
 	private UnmanagedMarshal(UnmanagedType type)
@@ -96,6 +100,26 @@ public sealed class UnmanagedMarshal
 				return new UnmanagedMarshal(unmanagedType);
 			}
 
+	// Define a custom-marshaler. This is an extension to MS.NET
+	public static UnmanagedMarshal DefineCustom
+			(Type typeRef, string cookie, string type, Guid guid)
+		{
+			UnmanagedMarshal custom =
+				new UnmanagedMarshal(UnmanagedType.CustomMarshaler);
+
+			if (type == null || type.Length == 0)
+				custom.marshalType = typeRef.AssemblyQualifiedName;
+			else
+				custom.marshalType = type;
+			// Should throw an exception if neither typeRef or type given
+
+			custom.marshalCookie = cookie;
+
+			// guid is ignored
+
+			return custom;
+		}
+
 	// Get the base type for marshalling behaviour.
 	public UnmanagedType BaseType 
 			{
@@ -203,6 +227,26 @@ public sealed class UnmanagedMarshal
 					}
 					break;
 
+					case UnmanagedType.CustomMarshaler:
+					{
+						// At a minimum, need space for type and 4 length-bytes
+						int size = 5;
+						int marshalTypeSize = Encoding.UTF8.GetByteCount(marshalType);
+						size += marshalTypeSize;
+						if (marshalCookie != null && marshalCookie.Length > 0)
+							size += Encoding.UTF8.GetByteCount(marshalCookie);
+
+						bytes = new byte[size];
+						bytes[0] = (byte)type;
+						bytes[1] = 0; // Empty guid string
+						bytes[2] = 0; // Empty native string
+						bytes[3] = (byte) Encoding.UTF8.GetBytes(marshalType,
+							0, marshalType.Length, bytes, 4);
+						bytes[marshalTypeSize+4] = (byte) Encoding.UTF8.GetBytes(marshalCookie,
+							0, marshalCookie.Length, bytes, marshalTypeSize + 5);
+						break;
+					}
+
 					default:
 					{
 						bytes = new byte [1];
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.