Как использовать C-структуру с 2D-массивом в С# Unity

Итак, у меня есть API C со следующей структурой

typedef struct mat4f_ { float m[4][4]; } mat4f;

Он передается как параметр одной из моих функций API:

void myFunction(const mat4f matrix);

Я экспортирую эту функцию в С# в Unity с помощью dll:

[DllImport ("mylib")] 
private static extern void myFunction(mat4f matrix);

Мой вопрос: , что я должен сделать для соответствующей структуры С#?

Сейчас у меня есть следующее:

[StructLayout(LayoutKind.Sequential)]
public struct mat4f
{
    public float[,] m;
}

и попробуйте использовать функцию следующим образом:

//Just make an identity matrix
mat4f matrix; 
matrix.m = new float[4, 4] { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } };

myFunction(matrix); //Call dll function

Это правильная вещь? Есть лучший способ сделать это?

Ответ 1

Для матрицы 4 × 4 вы можете использовать UnityEngine.Matrix4x4. Если вы хотите использовать свою собственную структуру, я рекомендую вам реализовать ее так же, как реализовано UnityEngine.Matrix4x4:

[StructLayout(LayoutKind.Sequential)]
public struct mat4f
{
    public float m00;
    public float m01;
    public float m02;
    public float m03;
    public float m10;
    public float m11;
    public float m12;
    public float m13;
    public float m20;
    public float m21;
    public float m22;
    public float m23;
    public float m30;
    public float m31;
    public float m32;
    public float m33;

    public static mat4f Identity = new mat4f
    {
        m11 = 1.0f,
        m22 = 1.0f,
        m33 = 1.0f,
        m44 = 1.0f
    };
}

Это blittable type. Blittable types не требуют преобразования, когда они передаются между управляемым и неуправляемым кодом.

Использование примера:

mat4f matrix = mat4f.Identity;
myFunction(matrix);  // Call DLL function

Существующие реализации аналогичны тем, которые я представил выше.

Ответ 2

Передача С# struct в импортированную функцию, как вы делаете, действительна, но вы должны указать длину массива в структуре, даже если вы позже укажете ее размер.

Объявление c в основном определяет массив длиной 16, поэтому я бы указал структуру С# следующим образом:

[StructLayout(LayoutKind.Sequential)]
public struct mat4f
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=16)] public float[,] m;
}

Вы можете узнать больше о том, как массивы сортируются здесь.