2

i'm still struggeling to marshal a quite complex struct from c++ to c#.

The struct in c++ is the following:

typedef struct {
    DWORD Flags;                    
    DWORD TimeCode;                 
    DWORD NodeMoving;   
    Matrix NodeRots[NUM_GYROS];
    Vector Position;                
    DWORD ContactPoints;            
    float channel[NUM_CHANNELS];
} Frame;

Vector:

typedef struct {
    union {
        struct {
            float x, y, z;
        };
        float Array[3];
    };
} Vector;

Matrix:

typedef struct {
    union {
        struct {
            float xx, xy, xz;       //This row is the right vector
            float yx, yy, yz;       //This row is the up vector
            float zx, zy, zz;       //This row is the forward vector
        };
        float Array[3][3];          //[row][col]
    };
} Matrix;

And here is what I have in c#:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public unsafe struct Matrix
    {
        public float xx;
        public float xy;
        public float xz;
        public float yx;
        public float yy;
        public float yz;
        public float zx;
        public float zy;
        public float zz;    
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public unsafe struct Vector{
        public float x;
        public float y;
        public float z; 
    }


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public unsafe struct Frame{
        public uint Flags;                  
        public uint TimeCode;                   
        public uint NodeMoving;             
        public fixed byte NodeRots[NUM_GYROS];
        public Vector Position;             
        public uint ContactPoints;          
        public fixed float channel[CHANNEL_ARRAY_SIZE];


        public unsafe float[] Channel
        {
            get
            {
                fixed (float* ptr = channel)
                {
                    float[] array = new float[CHANNEL_ARRAY_SIZE];

                    Marshal.Copy((IntPtr)ptr, array, 0, CHANNEL_ARRAY_SIZE);
                    return array;
                }
            }
        }

        public unsafe Matrix[] nodeRots{
            get{
                fixed (byte* ptr = NodeRots){
                    IntPtr ptr2 = (IntPtr)ptr;
                    Matrix[] array = new Matrix[NUM_GYROS];
                    for (int i = 0; i < array.Length; i++)
                    {
                        array[i] = (Matrix)Marshal.PtrToStructure(ptr2, typeof(Matrix));
                        IntPtr oldptr = ptr2;
                        ptr2 = new IntPtr(oldptr.ToInt32() + Marshal.SizeOf(typeof(Matrix)));
                    }
                    return array;
                }
            }
        }

the values Flags, TimeCode, NodeMoving, and NodeRots of the Frame struct are already passed correctly. The Members Position, ContactPoints and channel aren't marshalled correctly. I assume I have to do something with the Position Member, but I don't really know whats the mistake exactly.

3
  • Where does NodeRots come from? Shouldn't it be Matrix? Commented May 26, 2015 at 16:55
  • or at least Num_Gyros * 9 * 4 Commented May 26, 2015 at 16:57
  • I assume it should, but when i declare it as fixed Matrix i get a compling error: DLLHelper.Frame.nodeRots': Fixed size buffers type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double Commented May 26, 2015 at 17:20

1 Answer 1

2

I have already told you. You can't use fixed byte as an universal solution to problems.

This

public fixed byte NodeRots[NUM_GYROS];

must be

public fixed Matrix NodeRots[NUM_GYROS];

Then this:

Marshal.Copy((IntPtr)ptr, array, 0, CHANNEL_ARRAY_SIZE)

must be

Marshal.Copy((IntPtr)ptr, array, 0, CHANNEL_ARRAY_SIZE * sizeof(float));

Then for the nodeRots getter you don't really need the Marshal.PtrToStructure, because your struct can be marshaled directly.

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public unsafe struct Frame
{
    public uint Flags;
    public uint TimeCode;
    public uint NodeMoving;
    public fixed float nodeRots[NUM_GYROS * 9];
    public Vector Position;
    public uint ContactPoints;
    public fixed float channel[CHANNEL_ARRAY_SIZE];

    public unsafe float[] Channel
    {
        get
        {
            fixed (float* ptr = channel)
            {
                float[] array = new float[CHANNEL_ARRAY_SIZE];

                Marshal.Copy((IntPtr)ptr, array, 0, CHANNEL_ARRAY_SIZE * sizeof(float));
                return array;
            }
        }
    }

    public unsafe Matrix[] NodeRots
    {
        get
        {
            fixed (float* ptr = nodeRots)
            {
                Matrix[] array = new Matrix[NUM_GYROS];

                for (int i = 0, y = 0; i < array.Length; i++, y += 9)
                {
                    array[i].xx = ptr[y + 0];
                    array[i].xy = ptr[y + 1];
                    array[i].xz = ptr[y + 2];

                    array[i].yx = ptr[y + 3];
                    array[i].yy = ptr[y + 4];
                    array[i].yz = ptr[y + 5];

                    array[i].zx = ptr[y + 6];
                    array[i].zy = ptr[y + 7];
                    array[i].zz = ptr[y + 8];
                }

                return array;
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

i can't declare NodeRots as fixed Matrix as I get a compiling error: DLLHelper.Frame.nodeRots': Fixed size buffers type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double
@user1643687 Right... Try again. Modified to a fixed float[] array, and changed the NodeRots property
@xanatos perhaps you can help me with a question I've just asked? stackoverflow.com/questions/30592485/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.