C# - string 배열을 담은 구조체를 직렬화하는 방법
C# 구조체나 클래스 할당메모리 크기구하기
; http://lab.gamecodi.com/board/zboard.php?no=5096&id=GAMECODILAB_QnA_etc
위의 질문을 정리하면, 다음과 같은 구조체를 크기가 고정된 배열로 만들어
Marshal.SizeOf로 구하고 싶다는 것입니다.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct DirInfo
{
string[] DirNames;
string[] Time;
string[] size;
}
이런 문제는, 여러분들이 Marshal.SizeOf 코드의 개발자라고 생각하고 풀어 보면 됩니다.
첫 번째 문제는 string입니다. 도대체 string에 몇 개의 문자가 있을지 알 수 없으므로 고정된 크기를 산정할 수 없습니다. 또한 배열이라는 것도 마찬가지입니다. 배열의 크기가 정해지지 않았는데 당연히 고정된 크기를 구할 수 없습니다.
따라서 방법은, 크기를 고정시키기만 하면 됩니다.
우선, 가장 쉬운 방법으로 약간의 구조를 바꿔 다음과 같은 식으로 항목 별로 크기를 고정하는 것입니다.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct DirItem
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
public string DirName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
public string Time;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
public string size;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct DirInfo
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
public DirItem [] Items;
}
이런 경우에는 Marshal.SizeOf도 크기를 구할 수 있으므로 잘 동작합니다.
static void Main(string[] args)
{
DirItem dir = new DirItem();
Console.WriteLine(Marshal.SizeOf(dir)); // 3072 == 1024 * 3
DirInfo dir2 = new DirInfo();
Console.WriteLine(Marshal.SizeOf(dir2)); // 3145728 == 3072 * 1024
}
반면, (소스 코드를 변경할 수 없는) C++ DLL 측에서 구조가 이미 고정되어 있는 경우라면 다음과 같은 방법으로 우회할 수 있습니다.
public struct FixedString
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
string Item;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct DirInfo
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
FixedString[] DirNames;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
FixedString[] Time;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
FixedString[] size;
}
역시 크기는 동일하게 계산됩니다.
static void Main(string[] args)
{
DirInfo dir = new DirInfo();
Console.WriteLine(Marshal.SizeOf(dir)); // 3145728
}
그 외에 다음의 읽을거리도 있으니 참고하세요. ^^
Win32 Interop - 크기가 정해지지 않은 배열을 C++에서 C#으로 전달하는 경우
; https://www.sysnet.pe.kr/2/0/737
C#에서 Union 구조체 다루기
; https://www.sysnet.pe.kr/2/0/728
How to Interop DISPPARAMS
; https://www.sysnet.pe.kr/2/0/617
[in,out] 배열을 C#에서 C/C++로 넘기는 방법 - 두 번째 이야기
; https://www.sysnet.pe.kr/2/0/811
[in,out] 배열을 C#에서 C/C++로 넘기는 방법
; https://www.sysnet.pe.kr/2/0/810
구조체 포인터 인자에 대한 P/Invoke 정의
; https://www.sysnet.pe.kr/2/0/912
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]