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];