【问题标题】:Is it safe to point to the middle of a valuetype in C#/CLR?在 C#/CLR 中指向值类型的中间是否安全?
【发布时间】:2010-12-17 06:04:46
【问题描述】:

我有一个应该传递给 glLoadMatrixf 的 Matrix4D。为了克服 p/invoke 开销(即每次固定、编组等),我使用指针而不是通常的数组。所以我有两个问题。

  1. Matrix4D 基于复制粘贴类。它已经过测试并且可能进行了一些优化——不想重新发明轮子(我也很擅长数学)。无论如何,该类使用 16 个字段而不是 1 个固定数组(我猜该类是在 C# 1.0 时代编写的)。布局是顺序的,因此 GetPointer 方法只获取指向第一个字段的指针。问题是:会有一些填充问题吗?我的意思是,例如,运行时将浮点数扩展到双精度数,以便将一组字段索引为数组会得到垃圾。或者顺序布局是否通过规范阻止了这种情况?还是我应该严格遵守固定数组?

  2. 第二个问题是优化器可能进行的更改。矩阵是一个值类型,在其上调用 float* GetPointer()。恐怕优化器可能会以 GetPointer 指向一些垃圾的方式重新排列代码。

例如:

GL32NativeMethods.glLoadMatrixf((mat1 * mat2).GetPointer());

这样做是否安全?目前我这样做是为了确定(尽管我完全不确定):

Matrix4D tmp = mat1 * mat2;
GL32NativeMethods.glLoadMatrixf(tmp.GetPointer());

对于这个问题还有其他可能的解决方案吗? 附:调用 glLoadMatrixf 后,就不需要指针了。

更新

我担心的是,在调用 GetPointer() 和 glLoadMatrixf() 之间,优化器可能会丢弃该值(如我所想):

float* f = mat.GetPointer();

// 这里优化器决定丢弃 mat 变量,因为它不再使用了。

// 也许它现在用其他辅助值填充 mat 的内存区域(例如,对于 P/Invoke?)

GL32NativeMethods.glLoadMatrixf(f); // 引用丢弃的数据。

【问题讨论】:

  • 不固定就无法获得指针,所以应该没问题。
  • @Gabe:当被调用的方法返回时,从方法返回的指针不会仍然固定其对应的对象。但是,分配在堆栈上的值对象不需要固定。

标签: c# pointers opengl clr pinvoke


【解决方案1】:

嘿,我忘记了本机代码与类型无关,即重要的是实际的内存对齐。 我会试试这个:

public static extern void glLoadMatrixf(ref Matrix4D mat);
GL32NativeMethods.glLoadMatrixf(ref mat);

本机代码会被欺骗认为 mat 是一个浮点数组,尽管它实际上是一个带有浮点数组对齐的值类型。

【讨论】:

    【解决方案2】:

    我用以下方式包装了 OpenGL 方法:

        public static void UniformMatrix4(int location, Int32 count, bool transpose, float[] value) {
            unsafe {
                fixed (float* fp_value = value)
                {
                    Delegates.pglUniformMatrix4fv(location, count, transpose, fp_value);
                }
            }
        }
    
        [System.Runtime.InteropServices.DllImport(Library, EntryPoint = "glUniformMatrix4fv", ExactSpelling = true)]
        internal extern static unsafe void glUniformMatrix4fv(int location, Int32 count, bool transpose, float* value);
    

    然后,我可以使用 float[] 来指定矩阵分量。当然还有一个 Matrix 类,它定义了浮点数组和抽象数学运算。

    【讨论】:

    • 问题是,我不想在矩阵中有一个浮点数组。拥有一个浮点数组意味着每次复制矩阵时分配一个额外的数组。对于 .NET 可能没问题,但我也针对单声道,Windows 上的单声道使用缓慢的保守 gc。
    • 也许你是对的,但过于期待的优化是邪恶的。正确地写它,然后分析它。但是,您不应使用 GetPointer 例程返回指针,而应使用固定语句,即使在结构值(例如您的矩阵)上也是如此。
    猜你喜欢
    • 2012-12-07
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多