본문 바로가기
개발언어/C#

[c#] [StructLayout(LayoutKind.Sequential)]

by 창용이랑 2020. 11. 2.
728x90

Serializable : 문자로 변환하기 위해서 선언(? 알려주기정도..)해준다.

1. StructLayout(LayoutKind.Sequential) : 나 구조체야 라고 선언한다

(나 구조체야, 라는 표현보다는 마샬링 성능에 대한 부분이라 볼 수 있습니다.

[StructLayout] 키워드를 빼더라도 구조체는 사용할 수 있습니다.)

 

Sequential Layout은 Managed Memory에서 마샬링을 사용해 Unmanaged Memory로 옮길 때 각 필드의 순서가 Unmanaged Memory에서 유지되는 레이아웃이다. 위의 예제에서 MyStruct구조체는 [StructLayout(LayoutKind.Sequential)]을 사용하고 있는데, 이는 Managed 메모리 영역에서는 순서가 어떨지 모르지만, Unmanaged Memory로 옮겨질 때는 반드시 필드 순서대로 데이타가 옮겨진다는 것을 의미한다.

 

C#의 데이터가 순서대로 C++에 전달이 되어야 문제없이 사용가능하므로 [StructLayout(LayoutKind.Sequential, Size = 12)]를 사용합니다.

Size = 12부분은 구조체의 크기를 설정하는 부분 같습니다.


Pack=1 : Pack 단위로 만든다(Size만큼 정확히 만들어 준다)
CharSet=CharSet.Ansi : OS의 구조체 Padding값도 들어가 계산된다.

어떻게? 선언한 순서로 순차적으로 만들어 줘 라고
MarshalAs(UnmanagedType.ByValArray, SizeConst = 배열수)
    배열을 만들꼬다.. , (SizeConst = )개수 만큼!


이 외에도 UnmanagedType.ByValTStr(문자배열 Type은 string으로 줘도 된다)

Serializable]

[StructLayout(LayoutKind.Sequential, Pack=1)]

public struct _HMIData

{

    public _hmi_macsta hmi_macsta

}

[Serializable]

[StructLayout(LayoutKind.Sequential, Pack=1)]

public struct _hmi_macsta

{

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1100]

    public short[] oth_sta;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 298)]

    public short[] bcdv_sta1;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 298)]

    public short[] bcdv_sta2;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst= 15)]

    public string start_time;

}


열쉬미 만들었으면 생성해서 Read And Write ~~!!

public partial class ShmDataView : Form
{

    public _HMIData HMIData;

    public int ShmStructSize;

    public byte[] HMIBuffer;



public ShmDataView()

    {

        InitializeComponent();

        InitHMIData();

    }



    private void InitHMIData()

    {

        HMIData = new _HMIData();

        ShmStructSize = Marshal.SizeOf(HMIData);

        HMIBuffer = new byte[ShmStructSize];

    HMIData = (_HMIData)RawDeSerialize(HMIBuffer, HMIData.GetType());

    }





    public byte[] RawSerialize(object ShmStruct)

    {

        IntPtr buffer = Marshal.AllocHGlobal(ShmStructSize);

        Marshal.StructureToPtr(HMIData, buffer, false);

        byte[] RawData = new byte[ShmStructSize];

        Marshal.Copy(buffer, RawData, 0, ShmStructSize);

        Marshal.FreeHGlobal(buffer);

        return RawData;

    }



    public object RawDeSerialize(byte[] RawData, Type ShmData)

    {

        int RawSize = Marshal.SizeOf(ShmData);



        //Size Over

        if (RawSize > RawData.Length)

        {

            return null;

        }



        IntPtr buffer = Marshal.AllocHGlobal(RawSize);

        Marshal.Copy(RawData, 0, buffer, RawSize);

        object retobj = Marshal.PtrToStructure(buffer, ShmData);

        Marshal.FreeHGlobal(buffer);

        return retobj;

    }

}

 

public byte[] RawSerialize(object ShmStruct)
요녀석은 구조체로 되어있는 내용은 byte배열로 만들어준다

public object RawDeSerialize(byte[] RawData, Type ShmData)
요녀석은 byte배열로 되어있는 녀석을 구조체(object)로 반환해 준다.

그냥 sizeof하믄 안나온다
Marshal.SizeOf(객체)
이정도로 해줘야 C언어의 sizeof(구조체) 이렇게 한거와 같은 형태가 나온다

출처: https://softworld.tistory.com/67 [시행착오]

------------------------------------------------------------------------------