无法获取地址,获取大小或声明指向托管类型('T')的指针 [英] Cannot take the address of, get the size of, or declare a pointer to a managed type ('T')

查看:216
本文介绍了无法获取地址,获取大小或声明指向托管类型('T')的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么哦,这是不允许的:

Why oh why is this not allowed:

    private static unsafe byte[] ConvertStruct<T>(T str) where T: struct
    {
        T* ptr = &str;
        int size = Marshal.SizeOf(str);
        var arr = new byte[size];
        Marshal.Copy((IntPtr) ptr, arr, 0, size);
        return arr;
    }

我收到编译错误无法获取其地址,获取其大小或声明一个指向托管类型('T')的指针"

I get the compile error "Cannot take the address of, get the size of, or declare a pointer to a managed type ('T')"

还是结构"约束不够?从某种意义上说,它仍然可以是托管结构?

Or is the "struct" constraint not enough? In the sense that it could still be an managed struct?

我是否正确理解我的结构可能无法变蓝?如果是这样,blittable应该不是有效的约束吗?

Do I understand correctly that my struct might not be blittable? If so, should blittable not be a valid constraint?

推荐答案

就像Damian_The_Unbeliever所说,您不能为托管对象或包含托管字段的结构创建非托管指针.就像我在评论中说的那样,您没有实现可以确保编译时安全性以确保该结构满足那些要求的通用约束.因此,您无法指向泛型类型.

Like Damian_The_Unbeliever said, you can't make an unmanaged pointer of a managed object or of a struct that contains managed fields. And like I said in the comment, there is no generic restraint that you can implement that would ensure compile-time safety to make sure the struct would satisfy those requirements. As such, you can't make a pointer to a generic type.

但是,可能有解决方法. Marshal.StructureToPtr 方法将获取一个结构对象,并将其数据复制到 IntPtr 地址中.您可以将其与 Marshall.AllocHGlobal 结合使用,以实现所需的功能:

There may be a workaround, however. The Marshal.StructureToPtr method will take a structure object and copy its data into an IntPtr address. You can use it in conjunction with Marshall.AllocHGlobal to possibly achieve your desired functionality:

private static byte[] ConvertStruct<T>(ref T str) where T : struct
{
    int size = Marshal.SizeOf(str);
    IntPtr arrPtr = Marshal.AllocHGlobal(size);
    Marshal.StructureToPtr(str, arrPtr, true);
    var arr = new byte[size];
    Marshal.Copy(arrPtr, arr, 0, size);
    Marshal.FreeHGlobal(arrPtr);
    return arr;
}


正如Kris Vandermotten指出的那样,实际上没有必要使用 Marshal.AllocHGlobal .您可以固定数组,获取一个 IntPtr ,然后直接复制到 IntPtr :


As Kris Vandermotten points out, the Marshal.AllocHGlobal isn't actually necessary. You can pin the array, get an IntPtr for it, and copy to the IntPtr directly:

private static unsafe byte[] ConvertStruct<T>(ref T str) where T : struct
{
    int size = Marshal.SizeOf(str);
    var arr = new byte[size];

    fixed (byte* arrPtr = arr)
    {
        Marshal.StructureToPtr(str, (IntPtr)arrPtr, true);
    }

    return arr;
}

第一种方法的好处是,它不需要 unsafe 上下文即可工作.(如果您关心这种事情.)

The benefit to the first method, though, is that it doesn't require an unsafe context to work. (If you care about that kind of thing.)

这篇关于无法获取地址,获取大小或声明指向托管类型('T')的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆