Безопасно ли указывать на середину значения типа в C # / CLR? - PullRequest
0 голосов
/ 17 декабря 2010

У меня есть 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);// Ссылки на отброшенные данные.

Ответы [ 2 ]

0 голосов
/ 17 декабря 2010

Я обернул методы 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, который определяет массив чисел с плавающей точкой и абстрактных математических операций.

0 голосов
/ 17 декабря 2010

Хех, я забыл, что нативный код не зависит от типа, то есть имеет значение фактическое выравнивание памяти.Я попробую это:

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

Нативный код будет обманут, чтобы думать, что mat - это массив float, хотя на самом деле это тип значения с выравниванием массива float.

...