Microsoft MVP성태의 닷넷 이야기
.NET Framework: 686. C# - string 배열을 담은 구조체를 직렬화하는 방법 [링크 복사], [링크+제목 복사],
조회: 29798
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)
(시리즈 글이 16개 있습니다.)
.NET Framework: 112. How to Interop DISPPARAMS
; https://www.sysnet.pe.kr/2/0/617

.NET Framework: 137. C#에서 Union 구조체 다루기
; https://www.sysnet.pe.kr/2/0/728

.NET Framework: 141. Win32 Interop - 크기가 정해지지 않은 배열을 C++에서 C#으로 전달하는 경우
; https://www.sysnet.pe.kr/2/0/737

.NET Framework: 168. [in,out] 배열을 C#에서 C/C++로 넘기는 방법
; https://www.sysnet.pe.kr/2/0/810

.NET Framework: 169. [in, out] 배열을 C#에서 C/C++로 넘기는 방법 - 두 번째 이야기
; https://www.sysnet.pe.kr/2/0/811

.NET Framework: 183. 구조체 포인터 인자에 대한 P/Invoke 정의
; https://www.sysnet.pe.kr/2/0/912

.NET Framework: 472. C/C++과 C# 사이의 메모리 할당/해제 방법
; https://www.sysnet.pe.kr/2/0/1784

.NET Framework: 620. C#에서 C/C++ 함수로 콜백 함수를 전달하는 예제 코드
; https://www.sysnet.pe.kr/2/0/11099

.NET Framework: 627. C++로 만든 DLL을 C#에서 사용하기
; https://www.sysnet.pe.kr/2/0/11111

.NET Framework: 686. C# - string 배열을 담은 구조체를 직렬화하는 방법
; https://www.sysnet.pe.kr/2/0/11319

.NET Framework: 757. 포인터 형 매개 변수를 갖는 C++ DLL의 함수를 C#에서 호출하는 방법
; https://www.sysnet.pe.kr/2/0/11533

.NET Framework: 978. C# - GUID 타입 전용의 UnmanagedType.LPStruct
; https://www.sysnet.pe.kr/2/0/12444

C/C++: 158. Visual C++ - IDL 구문 중 "unsigned long"을 인식하지 못하는 #import
; https://www.sysnet.pe.kr/2/0/13128

.NET Framework: 2058. [in,out] 배열을 C#에서 C/C++로 넘기는 방법 - 세 번째 이야기
; https://www.sysnet.pe.kr/2/0/13141

.NET Framework: 2083. C# - C++과의 연동을 위한 구조체의 fixed 배열 필드 사용 (2)
; https://www.sysnet.pe.kr/2/0/13205

닷넷: 2152. Win32 Interop - C/C++ DLL로부터 이중 포인터 버퍼를 C#으로 받는 예제
; https://www.sysnet.pe.kr/2/0/13429




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




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 10/27/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 121  122  123  124  125  126  127  128  129  130  131  132  133  [134]  135  ...
NoWriterDateCnt.TitleFile(s)
1740정성태8/25/201433969.NET Framework: 458. 닷넷 GC가 순환 참조를 해제할 수 있을까요? [2]파일 다운로드1
1739정성태8/24/201427821.NET Framework: 457. 교착상태(Dead-lock) 해결 방법 - Lock Leveling [2]파일 다운로드1
1738정성태8/23/201423465.NET Framework: 456. C# - CAS를 이용한 Lock 래퍼 클래스파일 다운로드1
1737정성태8/20/201420946VS.NET IDE: 93. Visual Studio 2013 동기화 문제
1736정성태8/19/201426933VC++: 79. [부연] CAS Lock 알고리즘은 과연 빠른가? [2]파일 다운로드1
1735정성태8/19/201419509.NET Framework: 455. 닷넷 사용자 정의 예외 클래스의 최소 구현 코드 - 두 번째 이야기
1734정성태8/13/201421270오류 유형: 237. Windows Media Player cannot access the file. The file might be in use, you might not have access to the computer where the file is stored, or your proxy settings might not be correct.
1733정성태8/13/201427534.NET Framework: 454. EmptyWorkingSet Win32 API를 사용하는 C# 예제파일 다운로드1
1732정성태8/13/201435872Windows: 99. INetCache 폴더가 다르게 보이는 이유
1731정성태8/11/201428326개발 환경 구성: 235. 점(.)으로 시작하는 파일명을 탐색기에서 만드는 방법
1730정성태8/11/201423508개발 환경 구성: 234. Royal TS의 터미널(Terminal) 연결에서 한글이 깨지는 현상 해결 방법
1729정성태8/11/201419508오류 유형: 236. SqlConnection - The requested Performance Counter is not a custom counter, it has to be initialized as ReadOnly.
1728정성태8/8/201431736.NET Framework: 453. C# - 오피스 파워포인트(Powerpoint) 파일을 WinForm에서 보는 방법파일 다운로드1
1727정성태8/6/201421939오류 유형: 235. SignalR 오류 메시지 - Counter 'Messages Bus Messages Published Total' does not exist in the specified Category. [2]
1726정성태8/6/201420722오류 유형: 234. IIS Express에서 COM+ 사용 시 SecurityException - "Requested registry access is not allowed" 발생
1725정성태8/6/201422677오류 유형: 233. Visual Studio 2013 Update3 적용 후 Microsoft.VisualStudio.Web.PageInspector.Runtime 모듈에 대한 FileNotFoundException 예외 발생
1724정성태8/5/201427463.NET Framework: 452. .NET System.Threading.Thread 개체에서 Native Thread Id를 구하는 방법 - 두 번째 이야기 [1]파일 다운로드1
1723정성태7/29/201459888개발 환경 구성: 233. DirectX 9 예제 프로젝트 빌드하는 방법 [3]파일 다운로드1
1722정성태7/25/201422260오류 유형: 232. IIS 500 Internal Server Error - NTFS 암호화된 폴더에 웹 애플리케이션이 위치한 경우
1721정성태7/24/201425559.NET Framework: 451. 함수형 프로그래밍 개념 - 리스트 해석(List Comprehension)과 순수 함수 [2]
1720정성태7/23/201423489개발 환경 구성: 232. C:\WINDOWS\system32\LogFiles\HTTPERR 폴더에 로그 파일을 남기지 않는 설정
1719정성태7/22/201427414Math: 13. 동전을 여러 더미로 나누는 경우의 수 세기(Partition Number) - 두 번째 이야기파일 다운로드1
1718정성태7/19/201436865Math: 12. HTML에서 수학 관련 기호/수식을 표현하기 위한 방법 - MathJax.js [4]
1716정성태7/17/201436523개발 환경 구성: 231. PC 용 무료 안드로이드 에뮬레이터 - genymotion
1715정성태7/13/201431615기타: 47. 운영체제 종료 후에도 USB 외장 하드의 전원이 꺼지지 않는 경우 [3]
1714정성태7/11/201421574VS.NET IDE: 92. Visual Studio 2013을 지원하는 IL Support 확장 도구
... 121  122  123  124  125  126  127  128  129  130  131  132  133  [134]  135  ...