예제 #1
0
    public static void TestPInvokeMarkedWithUnmanagedCallersOnly()
    {
        Console.WriteLine($"Running {nameof(TestPInvokeMarkedWithUnmanagedCallersOnly)}...");

        // Call P/Invoke directly
        var pInvokeWrapperMethod = GetCallingUnmanagedCallersOnlyDirectlyType().GetMethod("CallPInvokeMarkedWithUnmanagedCallersOnly");

        Assert.Throws <NotSupportedException>(() => pInvokeWrapperMethod.Invoke(null, BindingFlags.DoNotWrapExceptions, null, new[] { (object)0 }, null));

        // Call P/Invoke via reflection
        var method = GetCallingUnmanagedCallersOnlyDirectlyType().GetMethod("PInvokeMarkedWithUnmanagedCallersOnly");

        Assert.Throws <NotSupportedException>(() => method.Invoke(null, BindingFlags.DoNotWrapExceptions, null, new[] { (object)0 }, null));

        // Call P/Invoke as a function pointer

        /*
         * void TestPInvokeMarkedWithUnmanagedCallersOnly_Throws()
         * {
         *      .locals init (native int V_0)
         *      IL_0000:  nop
         *      IL_0001:  ldftn      int InvalidCSharp.CallingUnmanagedCallersOnlyDirectly::PInvokeMarkedWithUnmanagedCallersOnly(int32)
         *      IL_0007:  stloc.0
         *
         *      IL_0008:  ldc.i4     1234
         *      IL_000d:  ldloc.0
         *      IL_000e:  calli      int32 stdcall(int32)
         *
         *      IL_0014:  ret
         * }
         */

        DynamicMethod testUnmanagedCallersOnly = new DynamicMethod("TestPInvokeMarkedWithUnmanagedCallersOnly_Throws", typeof(int), null, typeof(Program).Module);
        ILGenerator   il = testUnmanagedCallersOnly.GetILGenerator();

        il.DeclareLocal(typeof(IntPtr));
        il.Emit(OpCodes.Nop);

        // Get native function pointer of the callback
        il.Emit(OpCodes.Ldftn, method);
        il.Emit(OpCodes.Stloc_0);

        int n = 1234;

        il.Emit(OpCodes.Ldc_I4, n);
        il.Emit(OpCodes.Ldloc_0);
        il.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, typeof(int), new Type[] { typeof(int) });

        il.Emit(OpCodes.Ret);

        IntNativeMethodInvoker testNativeMethod = (IntNativeMethodInvoker)testUnmanagedCallersOnly.CreateDelegate(typeof(IntNativeMethodInvoker));

        Assert.Throws <NotSupportedException>(() => testNativeMethod());
    }
    public static void TestUnmanagedCallersOnlyViaUnmanagedCalli_ThrowException()
    {
        Console.WriteLine($"Running {nameof(TestUnmanagedCallersOnlyViaUnmanagedCalli_ThrowException)}...");

        /*
         * void UnmanagedCallersOnlyViaUnmanagedCalli_ThrowException()
         * {
         *      .locals init (native int V_0)
         *      IL_0000:  nop
         *      IL_0001:  ldftn      int CallbackViaUnmanagedCalliThrows(int32)
         *      IL_0007:  stloc.0
         *
         *      IL_0008:  ldc.i4     1234
         *      IL_000d:  ldloc.0
         *      IL_000e:  calli      int32 stdcall(int32)
         *
         *      IL_0014:  ret
         * }
         */
        DynamicMethod testUnmanagedCallersOnly = new DynamicMethod("UnmanagedCallersOnlyViaUnmanagedCalli_ThrowException", typeof(int), null, typeof(Program).Module);
        ILGenerator   il = testUnmanagedCallersOnly.GetILGenerator();

        il.DeclareLocal(typeof(IntPtr));
        il.Emit(OpCodes.Nop);

        // Get native function pointer of the callback
        il.Emit(OpCodes.Ldftn, typeof(Program).GetMethod(nameof(CallbackViaUnmanagedCalliThrows)));
        il.Emit(OpCodes.Stloc_0);

        int n = 1234;

        il.Emit(OpCodes.Ldc_I4, n);
        il.Emit(OpCodes.Ldloc_0);
        il.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, typeof(int), new Type[] { typeof(int) });

        il.Emit(OpCodes.Ret);

        IntNativeMethodInvoker testNativeMethod = (IntNativeMethodInvoker)testUnmanagedCallersOnly.CreateDelegate(typeof(IntNativeMethodInvoker));

        try
        {
            testNativeMethod();
            Assert.Fail($"Function {nameof(CallbackViaUnmanagedCalliThrows)} should throw");
        }
        catch (Exception e)
        {
            Assert.AreEqual(CallbackThrowsErrorCode, e.HResult);
        }
    }
    public static void TestUnmanagedCallersOnlyViaUnmanagedCalli()
    {
        Console.WriteLine($"Running {nameof(TestUnmanagedCallersOnlyViaUnmanagedCalli)}...");

        /*
         * void UnmanagedCallersOnlyViaCalli()
         * {
         *      .locals init (native int V_0)
         *      IL_0000:  nop
         *      IL_0001:  ldftn      int CallbackViaUnmanagedCalli(int32)
         *      IL_0007:  stloc.0
         *
         *      IL_0008:  ldc.i4     1234
         *      IL_000d:  ldloc.0
         *      IL_000e:  calli      int32 stdcall(int32)
         *
         *      IL_0014:  ret
         * }
         */
        DynamicMethod testUnmanagedCallersOnly = new DynamicMethod("UnmanagedCallersOnlyViaUnmanagedCalli", typeof(int), null, typeof(Program).Module);
        ILGenerator   il = testUnmanagedCallersOnly.GetILGenerator();

        il.DeclareLocal(typeof(IntPtr));
        il.Emit(OpCodes.Nop);

        // Get native function pointer of the callback
        il.Emit(OpCodes.Ldftn, typeof(Program).GetMethod(nameof(CallbackViaUnmanagedCalli)));
        il.Emit(OpCodes.Stloc_0);

        int n = 1234;

        il.Emit(OpCodes.Ldc_I4, n);
        il.Emit(OpCodes.Ldloc_0);
        il.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, typeof(int), new Type[] { typeof(int) });

        il.Emit(OpCodes.Ret);

        IntNativeMethodInvoker testNativeMethod = (IntNativeMethodInvoker)testUnmanagedCallersOnly.CreateDelegate(typeof(IntNativeMethodInvoker));

        int expected = DoubleImpl(n);

        Assert.AreEqual(expected, testNativeMethod());
    }
    public static int TestNativeCallableValid()
    {
        /*
         * void TestNativeCallable()
         * {
         *         .locals init ([0] native int ptr)
         *         IL_0000:  nop
         *         IL_0002:  ldftn      int32 CallbackMethod(int32)
         *
         *         IL_0012:  stloc.0
         *         IL_0013:  ldloc.0
         *         IL_0014:  ldc.i4     100
         *         IL_0019:  call       bool NativeMethods::CallNativeAdd(native int, int)
         *         IL_001e:  pop
         *         IL_001f:  ret
         *   }
         */
        DynamicMethod testNativeCallable = new DynamicMethod("TestNativeCallable", typeof(int), null, typeof(Program).Module);
        ILGenerator   il = testNativeCallable.GetILGenerator();

        il.DeclareLocal(typeof(IntPtr));
        il.Emit(OpCodes.Nop);

        // Get native function pointer of the callback
        il.Emit(OpCodes.Ldftn, typeof(Program).GetMethod("ManagedAddCallback"));
        il.Emit(OpCodes.Stloc_0);
        il.Emit(OpCodes.Ldloc_0);

        // return 111+100
        il.Emit(OpCodes.Ldc_I4, 111);
        il.Emit(OpCodes.Call, typeof(NativeMethods).GetMethod("CallManagedAdd"));
        il.Emit(OpCodes.Ret);
        IntNativeMethodInvoker testNativeMethod = (IntNativeMethodInvoker)testNativeCallable.CreateDelegate(typeof(IntNativeMethodInvoker));

        if (testNativeMethod() != 211)
        {
            return(0);
        }
        return(100);
    }