8

我愿意用unsafe。如何获取类虚拟表地址并将其转换为 int?

4

2 回答 2

4

(编辑:拍摄 - 忘了你还必须确保它不是内联的 - 见编辑)

您不需要不安全,但您确实需要确保该方法已经过 JIT(.PrepareMethod确实如此):

警告:我不完全确定(没有更多研究)这些数字在长期内有多准确;我知道它们曾经是准确的,因为我曾经用它来运行时交换方法实现......

using System;
using System.Runtime.CompilerServices;
void Main()
{
    long typeHandle = typeof(Foo).TypeHandle.Value.ToInt64();
    Console.WriteLine("addressOf(typeof(Foo)): 0x{0:x}", typeHandle);

    MethodInfo instanceMethod1 = typeof(Foo).GetMethod("InstanceFunc1");
    RuntimeHelpers.PrepareMethod(instanceMethod1.MethodHandle);
    long addressOfInstanceMethod1 = instanceMethod1.MethodHandle.GetFunctionPointer().ToInt64();
    Console.WriteLine("foo.InstanceFunc1:      0x{0:x}", addressOfInstanceMethod1);

    MethodInfo instanceMethod2 = typeof(Foo).GetMethod("InstanceFunc2");
    RuntimeHelpers.PrepareMethod(instanceMethod2.MethodHandle);
    long addressOfInstanceMethod2 = instanceMethod2.MethodHandle.GetFunctionPointer().ToInt64();
    Console.WriteLine("foo.InstanceFunc2:      0x{0:x}", addressOfInstanceMethod2);

    MethodInfo staticMethod = typeof(Foo).GetMethod("StaticFunc");
    RuntimeHelpers.PrepareMethod(staticMethod.MethodHandle);
    long addressOfStaticMethod = staticMethod.MethodHandle.GetFunctionPointer().ToInt64();
    Console.WriteLine("Foo.StaticFunc:         0x{0:x}", addressOfStaticMethod);
}

public class Foo
{
   [MethodImpl(MethodImplOptions.NoInlining)]
   public static int StaticFunc() { return 1; } 
   [MethodImpl(MethodImplOptions.NoInlining)]
   public int InstanceFunc1() { return 1; } 
   [MethodImpl(MethodImplOptions.NoInlining)]
   public int InstanceFunc2() { return 1; }
}
于 2013-01-05T03:58:13.710 回答
1

看看这篇文章——它适用于 .NET 1.1,但它只是一个开始。由于 JIT 内部没有很好的文档记录,我不确定这适用于当前框架版本的效果如何。

CLR 如何创建运行时对象

这个 SO question 也可能有用。

于 2013-01-05T03:26:19.390 回答