如何在c_中找到指向托管类的原始指针,并且希望它在内存中是原始大小的?显然,CLR不允许这样做——更确切地说,严格禁止这样做,因为托管类的非托管表示永远不应该出于稳定性和安全性的原因而使用——所以我正在寻找一种方法。我不是在寻找序列化-我确实需要一个托管类的转储,因为它是在原始内存中表示的。
更准确地说,我在下面的示例中寻找类似functiongetObjectPtr的内容:

IntPtr getObjectPtr(Object managedClass) {...}

void main() {
    var test=new TestClass();
    IntPtr* ptr_to_test=getObjectPtr(test);
    Console.WriteLine(ptr_to_test.ToString());
}

提前谢谢!
编辑:
我终于自己找到了一个解决方案,当我回来把它作为一个答案贴出来时,我对这么快就贴出来的答案感到非常惊讶…谢谢大家!这是非常迅速和完全出乎意料的。
最接近我的解决方案是@thehennyy的,但我不会发布它,因为@chino提出了更好的解决方案(抱歉,一开始我错了,我只是忘了再次引用指针)。它不要求代码是不安全的,而且更能容忍GC:
class Program
{
    // Here is the function in case anyone needs it.
    // Note, though, it does not preserve the handle while you work with
    // pointer, so it is less reliable than the code in Main():
    static IntPtr getPointerToObject(Object unmanagedObject)
    {
        GCHandle gcHandle = GCHandle.Alloc(unmanagedObject, GCHandleType.WeakTrackResurrection);
        IntPtr thePointer = Marshal.ReadIntPtr(GCHandle.ToIntPtr(gcHandle));
        gcHandle.Free();
        return thePointer;
    }
    class TestClass
    {
        uint a = 0xDEADBEEF;
    }
    static void Main(string[] args)
    {
        byte[] cls = new byte[16];

        var test = new TestClass();

        GCHandle gcHandle = GCHandle.Alloc(test, GCHandleType.WeakTrackResurrection);
        IntPtr thePointer = Marshal.ReadIntPtr(GCHandle.ToIntPtr(gcHandle));
        Marshal.Copy(thePointer, cls, 0, 16); //Dump first 16 bytes...
        Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(thePointer.ToInt32())));
        Console.WriteLine(BitConverter.ToString(cls));

        Console.ReadLine();

        gcHandle.Free();
    }
}
/* Example output (yours should be different):
40-23-CA-02
4C-38-04-01-EF-BE-AD-DE-00-00-00-80-B4-21-50-73

That field's value is "EF-BE-AD-DE", 0xDEADBEEF as it is stored in memory. Yay, we found it!
*/

霍维,现在我有点糊涂了。根据this文章,类中的前2个地址应该是指向syncblock和rtti结构的指针,因此第一个字段的地址必须从一开始就偏移2个字[32位系统中为8字节,64位系统中为16字节]。我的是64位;但是,正如您在输出中看到的,很明显第一个字段与对象地址的原始偏移量只有4个字节,这没有任何意义。
我问这个是separate question
也许我应该单独问这个问题,但我的解决方案可能有错误。

最佳答案

嘿,这就是你想要的吗?以下内容:

GCHandle gcHandle = GCHandle.Alloc(yourObject,GCHandleType.WeakTrackResurrection);
IntPtr thePointer = GCHandle.ToIntPtr(gcHandle);

08-27 22:21
查看更多