요즘 Win32API 소켓통신을 C#에 심고 있는데 C#은 강제 형변환이 어렵더라고요..ㅠㅠ
C#을 오랜만에 해봐서~ㅎㅎ
그래서 한~참을 뒤적 거리다 좋은걸 찾아서 올립니다~
//byte 배열을 구조체로
public static object ByteToStructure(byte[] data, Type type)
{
IntPtr buff = Marshal.AllocHGlobal(data.Length); // 배열의 크기만큼 비관리 메모리 영역에 메모리를 할당한다.
Marshal.Copy(data, 0, buff, data.Length); // 배열에 저장된 데이터를 위에서 할당한 메모리 영역에 복사한다.
object obj = Marshal.PtrToStructure(buff, type); // 복사된 데이터를 구조체 객체로 변환한다.
Marshal.FreeHGlobal(buff); // 비관리 메모리 영역에 할당했던 메모리를 해제함
if (Marshal.SizeOf(obj) != data.Length)// (((PACKET_DATA)obj).TotalBytes != data.Length) // 구조체와 원래의 데이터의 크기 비교
{
return null; // 크기가 다르면 null 리턴
}
return obj; // 구조체 리턴
}
// 구조체를 byte 배열로
public static byte[] StructureToByte(object obj)
{
int datasize = Marshal.SizeOf(obj);//((PACKET_DATA)obj).TotalBytes; // 구조체에 할당된 메모리의 크기를 구한다.
IntPtr buff = Marshal.AllocHGlobal(datasize); // 비관리 메모리 영역에 구조체 크기만큼의 메모리를 할당한다.
Marshal.StructureToPtr(obj, buff, false); // 할당된 구조체 객체의 주소를 구한다.
byte[] data = new byte[datasize]; // 구조체가 복사될 배열
Marshal.Copy(buff, data, 0, datasize); // 구조체 객체를 배열에 복사
Marshal.FreeHGlobal(buff); // 비관리 메모리 영역에 할당했던 메모리를 해제함
return data; // 배열을 리턴
}
좀 소스 그대로긴 해도 소켓통신에서 사용할때 도움이 많이 될거 같습니다.
그리고 사용시 주의 사항은 Marshal.SizeOf(obj); 이부분입니다.
struct PACKET_DATA
{
public int PacketType; // 패킷 타입
public int TotalBytes;
public byte[] Data;// 배열길이 1024
}
이런 구조체가 있다면 ..
Marshal.SizeOf(obj)는 byte의 배열 을 생각 안하고
사이즈를 무조건 12를 리턴합니다.
그럼 네트워크 통신에 데이터를 다 못 보내기 때문에~~
구조체 안에 크기를 선언해줍니다.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct PACKET_DATA
{
public int PacketType; // 패킷 타입
public int TotalBytes;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
public byte[] Data;//byte배열 길이 1024
}
그럼 Marshal.SizeOf(obj)는 1032를 리턴합니다~~~
다른 주의 사항도 있는데 함 필요할때 해보세요~