성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
[정성태] 만드실 수 있습니다. 단지, Unity 엔진 내의 스크립트와 W...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <div style='font-family: 맑은 고딕, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>구조체 포인터 인자에 대한 P/Invoke 정의</div> <br /> C/C++와의 연동 문제가 때때로 ^^ 어렵게 다가오기도 합니다. 결국 연동부분에서 직관적이지 않다는 것이 문제겠지요. 덕분에 다음과 같은 글들도 씌여졌었고. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > Win32 Interop - 크기가 정해지지 않은 배열을 C++에서 C#으로 전달하는 경우 ; <a target='_tab' href='http://www.sysnet.pe.kr/2/0/737'>http://www.sysnet.pe.kr/2/0/737</a> C#에서 Union 구조체 다루기 ; <a target='_tab' href='http://www.sysnet.pe.kr/2/0/728'>http://www.sysnet.pe.kr/2/0/728</a> How to Interop DISPPARAMS ; <a target='_tab' href='http://www.sysnet.pe.kr/2/0/617'>http://www.sysnet.pe.kr/2/0/617</a> [in,out] 배열을 C#에서 C/C++로 넘기는 방법 - 두 번째 이야기 ; <a target='_tab' href='http://www.sysnet.pe.kr/2/0/811'>http://www.sysnet.pe.kr/2/0/811</a> [in,out] 배열을 C#에서 C/C++로 넘기는 방법 ; <a target='_tab' href='http://www.sysnet.pe.kr/2/0/810'>http://www.sysnet.pe.kr/2/0/810</a> </pre> <br /> 이번에는, 다음 질문에 대한 답변으로 씌여지게 되었습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > C# Interop 관련 질문입니다. ; <a target='_tab' href='http://www.sysnet.pe.kr/3/0/904'>http://www.sysnet.pe.kr/3/0/904</a> ; <a target='_tab' href='http://www.sysnet.pe.kr/3/0/905'>http://www.sysnet.pe.kr/3/0/905</a> </pre> <br /> 요점은, 아래의 코드 조각에서 보는 것처럼, P/Invoke된 API에서 "ref DX_CAP" 인자에 대해 NULL이 가능해야 한다는 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > <b style='COLOR: blue'>public struct DX_CAP</b> { public ushort c1; public ushort c2; public ushort c3; }; [DllImport("...")] public static extern int fnStructTest(<b style='COLOR: blue'>ref DX_CAP cap</b>); </pre> <br /> <hr style='width: 50%' /><br /> <div style='font-family: 맑은 고딕, Consolas; font-size: 12pt; color: #2211AA; text-align: left; font-weight: bold'>해답 1: IntPtr 사용</div><br /> <br /> 일단, Null이 가능하도록 하기 위해서는 ref DX_CAP에 대한 처리를 IntPtr로 하는 수 밖에는 없습니다. 결국 Interop이 다음과 같이 지정되어야 한다는 것이고.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > [DllImport("...")] public static extern void fnStructTest(<b style='COLOR: blue'>IntPtr cap</b>); </pre> <br /> 그다음, DX_CAP은 IntPtr과의 변환을 편하게 할 수 있도록 class로 정의합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > [<b style='COLOR: blue'>StructLayout</b>(LayoutKind.Sequential)] public <b style='COLOR: blue'>class DXC_CAP</b> { public ushort ca_nbrdna; public ushort ca_stdely; public ushort ca_cnosig; }; </pre> <br /> 그럼, Null이 넘겨져야 할 경우에는 다음과 같이 간단하게 호출이 가능하겠고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > fnStructTest(<b style='COLOR: blue'>IntPtr.Zero</b>); </pre> <br /> 값을 넘겨 받아야 할 경우에는, fnStructTest를 호출할 때는 IntPtr로 변환해 주고, 호출 후에는 다시 IntPtr로부터 값을 복원해 주면 됩니다. 이를 코드로 정리하면 다음과 같습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > DXC_CAP inst2 = new DXC_CAP(); int marshalSize = 0; unsafe { marshalSize = sizeof(DX_CAP); } IntPtr ptrData = Marshal.AllocCoTaskMem(marshalSize); // 클래스 값 ==> IntPtr Marshal.StructureToPtr(inst2, ptrData, false); // 호출하고, fnStructTest(ptrData); // 다시 ptrData로부터 클래스 값 복원 Marshal.PtrToStructure(ptrData, inst2); // 메모리 해제 Marshal.FreeCoTaskMem(ptrData); </pre> <br /> 근데... 한 눈에 봐도... 너무 불편합니다. 좀 개선할 필요가 있어보입니다. ^^<br /> <br /> <hr style='width: 50%' /><br /> <br /> <div style='font-family: 맑은 고딕, Consolas; font-size: 12pt; color: #2211AA; text-align: left; font-weight: bold'>해답 2: 포인터 사용</div><br /> <br /> 다시 생각해서. 어쨌든 NULL이 가능하도록 해야 하니, unsafe 쪽으로 생각해 보는 것도 답이 될 수 있습니다.<br /> <br /> 코드를 정리해서, 다음과 같이 아예 구조체를 받는 포인터를 정의해주는 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > public <b style='COLOR: blue'>struct</b> DX_CAP { public ushort ca_nbrdna; public ushort ca_stdely; public ushort ca_cnosig; }; [DllImport("TestNativeAPI.dll")] <b style='COLOR: blue'>unsafe</b> public static extern void fnStructTest(<b style='COLOR: blue'>DX_CAP *cap</b>); </pre> <br /> 그럼, 게임 끝이군요. ^^<br /> <br /> NULL을 넘겨주어야 할 때는 다음과 같이 해주면 되고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > <b style='COLOR: blue'>unsafe</b> { fnStructTest(<b style='COLOR: blue'>null</b>); } </pre> <br /> 값을 전달받아야 할 때도 역시 unsafe와 포인터 구문을 사용해 주면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > DX_CAP inst; <b style='COLOR: blue'>unsafe</b> { fnStructTest(<b style='COLOR: blue'>&inst</b>); } </pre> <br /> unsafe와 포인터를 써야 하는 것에 대한 부담감이 있는데, 어느 쪽이든 선택을 해야 합니다. 몇 개 안되는 경우라면 그냥 해당 구조체 인자를 IntPtr로 받아들이는 P/Invoke 메서드를 중복 정의해주는 것도 답이겠지요.<br /> <br /> *** <a target='_tab' href='http://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?wid=912&boardid=331301885'>첨부된 프로젝트는 예제 코드</a>입니다. ***<br /> <br /><br /><hr /><span style='color: Maroon'>[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
8645
(왼쪽의 숫자를 입력해야 합니다.)