출처: http://sysnet.pe.kr/221115005092
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#으로 전달하는 경우; http://www.sysnet.pe.kr/2/0/737C#에서 Union 구조체 다루기; http://www.sysnet.pe.kr/2/0/728How to Interop DISPPARAMS; http://www.sysnet.pe.kr/2/0/617[in,out] 배열을 C# 에서 C/C++ 로 넘기는 방법 - 두번째 이야기; http://www.sysnet.pe.kr/2/0/811[in,out] 배열을 C# 에서 C/C++ 로 넘기는 방법; http://www.sysnet.pe.kr/2/0/810구조체 포인터 인자에 대한 P/Invoke 정의; http://www.sysnet.pe.kr/2/0/912