COM의 소개(파트 1) – COM이 무엇이며, 어떻게 사용하는가?
본 게시물은 ‘codeproject.com’에 게시된 글 ‘Introduction to COM - What It Is and How to Use It.’을 번역한 것입니다.
원 게시물은 https://www.codeproject.com/Articles/633/Introduction-to-COM-What-It-Is-and-How-to-Use-It에 게재되어 있습니다. 최대한 원문에 적힌 의도를 반영하고자 하였으나, 우리말로 읽었을 때 보다 자연스럽게 하고자 부득이 어순과 어휘를 조정한 부분도 있음을 양해 바랍니다.
또한 본 게시물에서 언급하고 있는 예제 소스 코드는 Visual C++ 6.0을 기준으로 작성되어 있기 때문에 후속 버전의 Visual Studio(또는 Visual Studio .NET)에서 자동 생성되는 COM 코드와는 다소 차이가 있음을 감안하고 읽으시기 바랍니다.
- COM의 소개(파트 1) – COM이 무엇이며, 어떻게 사용하는가? (1)
- COM의 소개(파트 1) – COM이 무엇이며, 어떻게 사용하는가? (2)
- COM의 소개(파트 1) – COM이 무엇이며, 어떻게 사용하는가? (3)
- COM의 소개(파트 1) – COM이 무엇이며, 어떻게 사용하는가? (4)
- COM의 소개(파트 1) – COM이 무엇이며, 어떻게 사용하는가? (5)
- COM의 소개(파트 1) – COM이 무엇이며, 어떻게 사용하는가? (6)
- COM의 소개(파트 1) – COM이 무엇이며, 어떻게 사용하는가? (7)
- COM의 소개(파트 1) – COM이 무엇이며, 어떻게 사용하는가? (8) [完]
기본 인터페이스 – IUnknown
모든 COM 인터페이스는 IUnknown
으로부터 파생됩니다. 이 인터페이스의 이름은 다소 오해의 소지가 있는데, 사실 이것은 ‘알 수 없는(unknown)’ 인터페이스라는 뜻이 아닙니다. 모든 COM 객체는 IUnknown
을 구현하고 있기 때문에 여러분이 어떤 COM 객체에 대해 IUnknown
포인터를 가지고 있다면, 여러분은 그 포인터가 정확히 어떤 형식의 객체를 가리키고 있는지 알 수 없다는 것을 이 이름이 의미하고 있습니다.
IUnknown
은 세 가지 메소드들을 갖습니다.
AddRef
- COM 객체에게 레퍼런스 카운트를 증가할 것을 알려줍니다. 여러분이 인터페이스 포인터의 복사본을 만들고, 원래의 포인터와 복사된 포인터를 함께 사용하려 할 때 이 메소드를 호출할 수 있습니다. 그러나 본 글에서 우리는
AddRef
를 굳이 사용할 필요는 없습니다. Release
- COM 객체에게 레퍼런스 카운트를 감소할 것을 알려줍니다. 앞서 언급한
Release
호출 예제를 참고하시기 바랍니다. QueryInterface
- COM 객체에게 인터페이스 포인터를 요청합니다. 여러분은 coclass가 하나 이상의 인터페이스를 구현하고 있을 때 이 메소드를 사용할 수 있습니다.
우리는 이미 예제 코드에서 Release
의 사용을 보았습니다. 그런데 QueryInterface
는 무엇일까요? 여러분이 CoCreateInstance
를 사용하여 COM 객체를 만들 때, 여러분은 인터페이스 포인터를 얻게 됩니다. COM 객체가 IUnknown
을 제외하고 하나 이상의 인터페이스를 구현하고 있을 때, 여러분은 QueryInterface
를 사용하여 여러분이 필요로 하는 추가적인 인터페이스 포인터를 얻을 수 있습니다. QueryInterface
의 원형은 다음과 같습니다.
HRESULT IUnknown::QueryInterface(
REFIID iid,
void ** ppv);
파라미터의 의미는 다음과 같습니다.
iid
- 여러분이 요청하게 될 인터페이스에 대한
IID
입니다. ppv
- 인터페이스 포인터에 대한 포인터입니다. COM 객체가
iid
파라미터로 지정한 인터페이스를 구현하고 있다면, 그에 대한 인터페이스 포인터가 이 매개변수를 통해 반환됩니다. - 앞서 언급한 쉘 바로가기 예제를 봅시다. 쉘 바로가기를 만들 수 있는 coclass는
IShellLink
와IPersistFile
을 구현하고 있습니다. 여러분이 이미 해당 COM 객체에 대해IShellLink
형의 인터페이스 포인터를 가지고 있다면, 같은 COM 객체에게IPersistFile
형의 인터페이스 포인터도 얻을 수 있습니다. 그 방법은 다음과 같습니다.
HRESULT hr;
IShellLink * pISL;
IPersistFile * pIPF;
hr = pISL->QueryInterface(IID_IPersistFile, (void **)&pIPF);
그 다음 QueryInterface
가 정상적으로 작동하였는지 확인하기 위하여 SUCCEEDED
또는 FAILED
매크로를 사용하여 hr
의 값을 검사합니다. 다른 형식의 인터페이스 포인터를 얻는데 성공하였다면, 여러분은 이 새로운 인터페이스 포인터도 사용할 수 있습니다. 단, 다른 인터페이스처럼 사용이 끝났을 때 여러분은 필히 pIPF->Release()
를 호출하여야 합니다.