성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Reordering on an Alpha processor ;...
[정성태] 공유 감사합니다. ^^ 참고로, WPF에서 WindowsF...
[Tom Lee] 답변 감사합니다. 나름의 해결책 연구해보고 여기에도 공유해봅니다...
[정성태] 아래의 글을 보면, MoveWindow 하면 될 듯한데요. ^^...
[Tom Lee] 안녕하세요 올려주신 글 참고하여 WPF 어플리케이션 안에 Uni...
[정성태] A graphical depiction of the steps ...
[정성태] 질문을 주셔서 출판사 측에 문의를 했습니다. 약 한 달 정도 후...
[Thorondor
] @정성태 개인 블로그인데도 거의 커뮤니티 급 인 것 같아요. 요...
[정성태] Roll A Lisp In C - Reading ; https...
[정성태] Java - How to use the Foreign Funct...
글쓰기
제목
이름
암호
전자우편
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'>[in,out] 배열을 C#에서 C/C++로 넘기는 방법</div><br /> <br /> 가령, long 형 배열을 C/C++에 넘겨주고, C/C++ 측에서 해당 배열의 내용을 채운 후 반환해 주는 메서드라면 다음과 같이 IDL 정의를 해줄 수 있습니다.<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;' > [ object, uuid(1A38076B-3D6D-4F20-8B4D-C72EF6AE1204), dual, nonextensible, helpstring("IMyTest Interface"), pointer_default(unique) ] interface IMyTest : IDispatch { [id(0x3003), helpstring("method PrepareBuf1")] HRESULT PrepareBuf(<b style='COLOR: blue'>[in, out, size_is(bufLength)] __int64 buffer []</b>, [in] int bufLength); }; </pre> <br /> 그런데, tlbimp.exe(또는 Visual Studio의 DLL 참조)를 이용하여 interop DLL을 생성해 보면, PrepareBuf의 함수 형식이 다음과 같이 정의되는 것을 볼 수 있습니다.<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;' > tlbimp testatl.dll /out:interop.testatl.dll public virtual void PrepareBuf(<b style='COLOR: blue'>ref long buffer</b>, int bufLength); </pre> <br /> 오호... tlbimp.exe로써는, 감당이 안되는 IDL 구문이라는 것인데요. 그렇다면 이를 해결하기 위해서 생각해 볼 수 있는 것이 배열 자체를 포인터로 넘겨보는 정도일텐데, 약간 찜찜하긴 해도 4byte(혹은 8byte) 값으로 넘기는 것은 ^^ 너무 잘 동작합니다.<br /> <br /> 그래서 C# 측에서, 배열 자체를 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;' > [STAThread] static void Main(string[] args) { interop.testatl.MyTestClass mtc = new interop.testatl.MyTestClass(); long [] test = new long[5]; // IntPtr ptr = <b style='COLOR: blue'>Marshal.UnsafeAddrOfPinnedArrayElement</b>(test, 0); // mtc.PrepareBuf(<b style='COLOR: blue'>ptr.ToInt64()</b>, 5); // 코드 변경: 2020-05-07 GCHandle gcHandle = GCHandle.Alloc(test, GCHandleType.Pinned); try { mtc.PrepareBuf(<b style='COLOR: blue'>gcHandle.AddrOfPinnedObject().ToInt64()</b>, 5); } finally { gcHandle.Free(); } for (int i = 0; i < 5; i++) { Console.WriteLine(test[i]); } } </pre> <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;' > STDMETHOD(PrepareBuf2)(__int64 buffer, int bufLength) { <b style='COLOR: blue'>__int64 *pBuffer = (__int64 *)buffer;</b> for (int i = 0; i < bufLength; i ++ ) { pBuffer[i] = i; } return S_OK; } </pre> <br /> 물론, 이 방법은 out-of-process COM 개체로 만들면 프로세스 주소 공간이 달라지기 때문에 동작하지 않습니다. 하지만, In-proc COM 개체만으로 사용하실 분들이라면 이 방법이 나쁘다고 볼 수는 없습니다.<br /> <br /> 그렇긴 해도,,, 뭔가 개선 방법이 있지 않을까요? ^^<br /> <a target='_blank' href='http://www.sysnet.pe.kr/2/0/811'>다음 토픽</a>에 그 방법을 알아보겠습니다.<br /> <br /><br /><hr /><span style='color: Maroon'>[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
5826
(왼쪽의 숫자를 입력해야 합니다.)