[유니티/C#]GCHandle이란 무엇인가

프로그래밍/유니티2018. 4. 12. 00:57

안녕하세요. 개발자 드리머즈입니다.


GCHandle에 대해 조사해보겠습니다.


GCHandle은 찾아보니 Unity가 아닌 .NET Framework에 존재하는 구조체입니다.(System.Runtime.InteropServices에 속함)


https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle(v=vs.110).aspx



Provides a way to access a managed object from unmanaged memory.


라고 설명이 되어있습니다. 관리되지 않는 메모리부터 관리되는 객체에 접근할 방법을 제공한다?라고 하는데 이해가 잘 되지 않습니다.

https://stackoverflow.com/questions/7688287/what-exactly-is-the-contract-of-gchandle-allocobject를 읽어보면 조금 이해가 되는 것 같습니다.

GCHandle에서 GC는 Garbage Colloector의 약자인 것 같습니다.


http://lab.gamecodi.com/board/zboard.php?id=GAMECODILAB_QnA_etc&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=hit&desc=asc&no=3465

에도 좋은 설명이 있습니다.


GCHandle.Alloc은 GC Heap에 할당된 객체를 pinning하는 것으로 오히려 GC에 부담을 줍니다. 다음의 문서에도 나오지만,

GCHandle.Alloc Method (Object) - https://msdn.microsoft.com/ko-kr/library/a95009h1(v=vs.110).aspx

GCHandle.Alloc은 native 코드에서 관리 힙의 객체를 접근해야 할 경우를 위해 만들어진 것입니다.


또 다른 좋은 설명이 있습니다.(https://blog.naver.com/indpkr/220064279914)


이 기종간의 데이터를 전달함에 있어서 가장 간편하고 빠른 방법은 공유메모리를 만들고 양쪽 시스템이 이를 접근하게 만들어주는 것입니다.

하지만 C#에서 메모리를 만드는 경우, 가비지콜렉션이 언제 발생할지 모르는 상황이 발생하기 때문에, 네이티브가 안전하게 메모리 영역에 접근하기가 쉽지 않습니다. 이를 위해 .NET이 제공하는 함수 중에 GCHandle.Alloc이라는 함수가 있습니다.

GCHandle.Alloc 함수는 C#에서 생성한 메모리를 고정시켜주는 역할을 수행하며, 이를 IntPtr로 네이티브에 전달하면 네이티브에서 이를 접근하는 것이 가능합니다.


제가 접한 GCHandle을 사용하는 코드는 아래와 같습니다.


1
2
pixels = webcamscreen.GetPixels32();
pixelsHandle = GCHandle.Alloc(pixels, GCHandleType.Pinned);
cs


https://msdn.microsoft.com/en-us/library/1246yz8f(v=vs.110).aspx

에 Alloc 함수에 대한 설명이 있습니다.


1
public static GCHandle Alloc(object value, GCHandleType type)
cs

GCHandle.Alloc()함수가 사용됐습니다. Alloc 함수는 인자를 2개 가집니다.

첫 번째 인자는 GCHandle을 사용할 객체를 넣으면 되고, 두 번째 인자는 생성할 GCHandle의 타입을 넣으면 됩니다.


GCHandle의 타입은 4개가 있는데 위의 예제에서 사용된 Pinned 속성만 간단하게 보겠습니다.

(https://msdn.microsoft.com/en-us/library/83y4ak54(v=vs.110).aspx)


GCHandle로 관리하는 객체의 주소를 고정시키는 것 같습니다. 이렇게 하면 GC의 효율성이 떨어지니 가능하면 빨리 Free 함수를 사용하라고 합니다.


GCHandle에는 AddrOfPinnedObject()라는 함수가 있습니다. 이 함수는 말 그대로 Pinned된 객체의 주소를 반환하는 함수입니다.


C#에서 만들어진 객체를 C++에서 접근할 수 있도록할 때 GCHandle.Alloc()를 사용합니다.

작성자

Posted by 드리머즈

관련 글

댓글 영역