June 02, 2005 12:16 am (permalink)

Using an unmanaged function pointer from managed code

Today, Peter asked me an interesting question he had while implementing OLE2 Drag'n Drop in SWF: he got a native function pointer from unmanaged code and tried to invoke it from managed land. Unfortunately, such a pointer isn't managed to a delegate on .NET 1.x, so we were looking for a little hack. What we need is basically a function which looks like this in IL:

.method static int32 GetData (native int pfn, native int foo, native int bar) { ldarg.2 // push bar ldarg.1 // push foo ldarg.0 // push pfn calli unmanaged stdcall native int(native int, native int, native int) ret }

However, we wanted to do that without using an extra dll for that - so I had a really cool idea: using a dynamic module.

So here's the code:

static MethodInfo CreateMethod () { AssemblyName aname = new AssemblyName ("temp"); AssemblyBuilder ass = AppDomain.CurrentDomain.DefineDynamicAssembly ( aname, AssemblyBuilderAccess.Run); ModuleBuilder mb = ass.DefineDynamicModule ("temp"); TypeBuilder tb = mb.DefineType ("Test", TypeAttributes.Public); Type[] ptypes = new Type[] { typeof (int) }; MethodBuilder method = tb.DefineMethod ( "Hello", MethodAttributes.Static | MethodAttributes.Public, typeof (int), ptypes); ILGenerator ig = method.GetILGenerator (); ig.Emit (OpCodes.Nop); ig.Emit (OpCodes.Ldc_I4_1); ig.Emit (OpCodes.Ret); Type t = tb.CreateType (); MethodInfo m = t.GetMethod ("Hello"); return m; }

This returns you a MethodInfo which you can just Invoke.

Note that you need the CreateType() and the GetMethod at the end.
If at all possible, you should also store the returned MethodInfo somewhere and reuse it rather than creating a new one each time.

Posted by martin at June 02, 2005 12:16 am.