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

发布于 2024-10-07 22:15:05 字数 1030 浏览 0 评论 0原文

我有一个 Matrix4D,应该传递给 glLoadMatrixf。为了克服 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());

这个问题还有其他可能的解决方案吗? PS 调用 glLoadMatrixf 后,不再需要指针。

UPD

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

float* f = mat.GetPointer();

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

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

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

I have a Matrix4D that should be passed to glLoadMatrixf. To overcome p/invoke overhead (i.e. pinning, marshaling etc. each time), I'm using pointers instead of usual arrays. So I have two issues.

  1. Matrix4D is based on a copypasted class. 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). The layout is sequential, so that GetPointer method just gets a pointer to the very first field. 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. I'm afraid the optimizer may rearrange the code in such a way that GetPointer would point to some garbage.

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?
P.S. After the call to glLoadMatrixf, the pointer isn't needed.

UPD

My concern is that in between the calls to GetPointer() and glLoadMatrixf() the value may be discarded by the optimizer (as I suppose):

float* f = mat.GetPointer();

// Here the optimizer decides to discard mat variable because it isn't used anymore.

// Maybe it now fills the memory area of mat with other helper values (for P/Invoke, for example?)

GL32NativeMethods.glLoadMatrixf(f); // References discarded data.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧城烟雨 2024-10-14 22:15:05

呵呵,我完全忘记了本机代码与类型无关,即实际的内存对齐很重要。
我将尝试这个:

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

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

Heh, I plumb forgot that native code is type-agnostic, i.e. 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.

杀手六號 2024-10-14 22:15:05

我用以下方式包装了 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 类,它定义浮点数组和抽象数学运算。

I wrapped OpenGL methods in the following way:

    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. Of course there's a Matrix class which defines the array of floats and abstract math operations.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文