简体   繁体   English

在C#/ CLR中指向值类型的中间是否安全?

[英]Is it safe to point to the middle of a valuetype in C#/CLR?

I have a Matrix4D that should be passed to glLoadMatrixf. 我有一个Matrix4D,应该传递给glLoadMatrixf。 To overcome p/invoke overhead (ie pinning, marshaling etc. each time), I'm using pointers instead of usual arrays. 为了克服p / invoke的开销(即每次都进行固定,封送等),我使用了指针而不是通常的数组。 So I have two issues. 所以我有两个问题。

  1. Matrix4D is based on a copypasted class. Matrix4D基于复制粘贴的类。 It's tested and probably optimized a bit -- didn't want to reinvent the wheel (also I suck at math). 它已经过测试并且可能做了一些优化-不想重新发明轮子(我也很喜欢数学)。 Anyway, that class uses 16 fields instead of 1 fixed array (the class was written in the C# 1.0 era I guess). 无论如何,该类使用16个字段而不是1个固定数组(我猜这个类是在C#1.0时代编写的)。 The layout is sequential, so that GetPointer method just gets a pointer to the very first field. 布局是顺序的,因此GetPointer方法仅获取指向第一个字段的指针。 THE QUESTION is: can there be some padding problems? 问题是:是否存在一些填充问题? I mean cases when, for example, the runtime extends floats to doubles so that indexing a pack of fields as an array would get garbage. 我的意思是说,例如,运行时扩展将浮点数加倍,以至于将一包字段索引为一个数组会造成垃圾。 Or does sequential layout prevent that by specs? 还是按规范进行顺序布局可以防止这种情况? Or should I adhere strictly to fixed arrays? 还是我应该严格遵守固定数组?

  2. The second issue is possible alterations by the optimizer. 第二个问题是优化程序可能进行的更改。 The matrix is a value type, on which float* GetPointer() is called. 矩阵是一个值类型,在其上调用float * GetPointer()。 I'm afraid the optimizer may rearrange the code in such a way that GetPointer would point to some garbage. 恐怕优化器可能会重新排列代码,使GetPointer指向某些垃圾。

For example: 例如:

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

Is it safe to do, or not? 是否安全? Currently I'm doing this to be sure (though I'm not sure at all): 目前,我正在这样做以确保(尽管我不确定):

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

Are there other possible solutions to this problem? 还有其他可能的解决方案吗? PS After the call to glLoadMatrixf, the pointer isn't needed. PS在调用glLoadMatrixf之后,不需要该指针。

UPD UPD

My concern is that in between the calls to GetPointer() and glLoadMatrixf() the value may be discarded by the optimizer (as I suppose): 我担心的是,在对GetPointer()和glLoadMatrixf()的调用之间,优化器可能会舍弃该值(正如我想的那样):

float* f = mat.GetPointer(); float * f = mat.GetPointer();

// Here the optimizer decides to discard mat variable because it isn't used anymore. //在这里,优化器决定放弃mat变量,因为不再使用它。

// Maybe it now fills the memory area of mat with other helper values (for P/Invoke, for example?) //也许现在它用其他辅助值填充了mat的内存区域(例如,对于P / Invoke?)

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

Heh, I plumb forgot that native code is type-agnostic, ie it's actual memory alignment that matters. 嘿,我忘记了本机代码是类型无关的,即实际的内存对齐很重要。 I'll try out this one: 我将尝试以下方法:

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

Native code will be tricked into thinking that mat is an array of floats, although it's actually a valuetype with the alignment of a float array. 本机代码将被欺骗以为mat是一个float数组,尽管它实际上是一个与float数组对齐的valuetype。

I wrapped OpenGL methods in the following way: 我用以下方式包装了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);

Then, I can use a float[] for specifying matrix components. 然后,我可以使用float []指定矩阵分量。 Of course there's a Matrix class which defines the array of floats and abstract math operations. 当然,有一个Matrix类定义了浮点数和抽象数学运算的数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM