스레드가 COM 라이브러리를 초기화한 후에는 스레드가 COM 인터페이스를 사용하는 것이 안전합니다. COM 인터페이스를 사용하려면 프로그램에서 먼저 해당 인터페이스를 구현하는 개체의 인스턴스를 만듭니다.
일반적으로 COM 개체를 만드는 방법에는 두 가지가 있습니다.
- 개체를 구현하는 모듈은 해당 개체의 인스턴스를 만들도록 특별히 설계된 함수를 제공할 수 있습니다.
- 또는 COM은 CoCreateInstance명명된 제네릭 생성 함수를 제공합니다.
예를 들어 COM 인터페이스란?항목에서 가상의 Shape 개체를 사용합니다.. 이 예제에서 Shape 개체는 IDrawable인터페이스를 구현합니다.
Shape 개체를 구현하는 그래픽 라이브러리는 다음 서명이 있는 함수를 내보낼 수 있습니다.
// Not an actual Windows function.
HRESULT CreateShape(IDrawable** ppShape);
이 함수를 사용하면 다음과 같이 새 Shape 개체를 만들 수 있습니다.
IDrawable *pShape;
HRESULT hr = CreateShape(&pShape);
if (SUCCEEDED(hr))
{
// Use the Shape object.
}
else
{
// An error occurred.
}
ppShape 매개 변수는 포인터-포인터-IDrawable형식입니다. 이전에 이 패턴을 못했다면 이중 간접 참조가 수수께끼일 수 있습니다.
CreateShape 함수의 요구 사항을 고려합니다. 함수는 호출자에게 IDrawable 포인터를 다시 제공해야 합니다. 그러나 함수의 반환 값은 오류/성공 코드에 이미 사용됩니다. 따라서 함수에 대한 인수를 통해 포인터를 반환해야 합니다. 호출자는 IDrawable* 형식의 변수를 함수에 전달하고 함수는 이 변수를 새 IDrawable 포인터로 덮어씁 수 있습니다. C++에서는 함수가 매개 변수 값을 덮어쓰는 두 가지 방법, 즉 참조로 전달하거나 주소를 통해 전달합니다. COM은 후자의 주소를 통한 전달을 사용합니다. 포인터의 주소는 포인터-포인터이므로 매개 변수 형식은 IDrawable**합니다.
다음은 진행 중인 작업을 시각화하는 데 도움이 되는 다이어그램입니다.
CreateShape 함수는 pShape(&pShape)의 주소를 사용하여 pShape 새 포인터 값을 작성합니다.
CoCreateInstance: 개체를 만드는 일반적인 방법
CoCreateInstance 함수는 개체를 만들기 위한 제네릭 메커니즘을 제공합니다. CoCreateInstance 이해하려면 두 개의 COM 개체가 동일한 인터페이스를 구현할 수 있고 한 개체는 둘 이상의 인터페이스를 구현할 수 있습니다. 따라서 개체를 만드는 제네릭 함수에는 두 가지 정보가 필요합니다.
- 어떤 개체를 만들까요?
- 어떤 인터페이스를 개체에서 가져올 것인지.
그러나 함수를 호출할 때 이 정보를 어떻게 나타낼 수 있을까요? COM에서 개체 또는 인터페이스는 GUID(globally unique identifier )라고 하는 128비트 번호를 할당하여 식별됩니다. GUID는 실질적으로 고유하게 만드는 방식으로 생성됩니다. GUID는 중앙 등록 기관 없이 고유 식별자를 만드는 방법의 문제에 대한 해결 방법입니다. GUID는 때때로 범용 고유 식별자 라고도 불립니다 (UUID). COM 이전에는 DCE/RPC(분산 컴퓨팅 환경/원격 프로시저 호출)에서 사용되었습니다. 새 GUID를 만들기 위한 몇 가지 알고리즘이 있습니다. 이러한 모든 알고리즘이 고유성을 엄격하게 보장하는 것은 아니지만 실수로 동일한 GUID 값을 두 번 만들 확률은 매우 작으며 사실상 0입니다. GUID를 사용하여 개체 및 인터페이스뿐만 아니라 모든 종류의 엔터티를 식별할 수 있습니다. 그러나 이 모듈에서 문제가 되는 유일한 용도입니다.
예를 들어 Shapes 라이브러리는 다음 두 개의 GUID 상수로 선언할 수 있습니다.
extern const GUID CLSID_Shape;
extern const GUID IID_IDrawable;
(이러한 상수의 실제 128비트 숫자 값이 다른 곳에서 정의되어 있다고 가정할 수 있습니다.) 상수 CLSID_ShapeShape 개체를 식별하는 반면 상수 IID_IDrawableIDrawable 인터페이스를 식별합니다. 접두사 "CLSID"는 클래스 식별자의미하며, 접두사 IID인터페이스 식별자의미합니다. COM의 표준 명명 규칙입니다.
이러한 값을 지정하면 다음과 같이 새 Shape 인스턴스를 만듭니다.
IDrawable *pShape;
hr = CoCreateInstance(CLSID_Shape, NULL, CLSCTX_INPROC_SERVER, IID_IDrawable,
reinterpret_cast<void**>(&pShape));
if (SUCCEEDED(hr))
{
// Use the Shape object.
}
else
{
// An error occurred.
}
CoCreateInstance 함수에는 5개의 매개 변수가 있습니다. 첫 번째 및 네 번째 매개 변수는 클래스 식별자 및 인터페이스 식별자입니다. 실제로 이러한 매개 변수는 함수에 "Shape 개체를 만들고 IDrawable 인터페이스에 대한 포인터를 제공합니다."라고 말합니다.
두 번째 매개 변수를 NULL 설정합니다. (이 매개 변수의 의미에 대한 자세한 내용은 COM 설명서의 집계 항목을 참조하세요.) 세 번째 매개 변수는 개체에 대한 실행 컨텍스트 지정하는 것이 주된 목적인 플래그 집합을 사용합니다. 실행 컨텍스트는 개체가 애플리케이션과 동일한 프로세스에서 실행되는지 여부를 지정합니다. 동일한 컴퓨터의 다른 프로세스에서 또는 원격 컴퓨터에서 다음 표에서는 이 매개 변수에 대한 가장 일반적인 값을 보여줍니다.
| 깃발 | 묘사 |
|---|---|
| CLSCTX_INPROC_SERVER | 동일한 프로세스입니다. |
| CLSCTX_LOCAL_SERVER | 다른 프로세스, 동일한 컴퓨터. |
| CLSCTX_REMOTE_SERVER | 다른 컴퓨터. |
| CLSCTX_ALL | 개체에서 지원하는 가장 효율적인 옵션을 사용합니다. (순위는 가장 효율적인 순위부터 최소 효율까지입니다. in-process, out-of-process 및 cross-computer.) |
특정 구성 요소에 대한 설명서에서는 개체가 지원하는 실행 컨텍스트를 알려줄 수 있습니다. 그렇지 않은 경우 CLSCTX_ALL사용합니다. 개체가 지원하지 않는 실행 컨텍스트를 요청하면 CoCreateInstance 함수는 오류 코드 REGDB_E_CLASSNOTREG반환합니다. 이 오류 코드는 CLSID가 사용자의 컴퓨터에 등록된 구성 요소와 일치하지 않음을 나타낼 수도 있습니다.
다섯 번째 매개 변수는 CoCreateInstance 인터페이스에 대한 포인터를 받습니다. CoCreateInstance 제네릭 메커니즘이므로 이 매개 변수를 강력하게 입력할 수 없습니다. 대신 데이터 형식이 void**호출자는 포인터의 주소를 void** 형식으로 강제 변환해야 합니다. 이것이 이전 예제에서 reinterpret_cast의 용도입니다.
CoCreateInstance반환 값을 확인하는 것이 중요합니다. 함수가 오류 코드를 반환하는 경우 COM 인터페이스 포인터가 유효하지 않으며 역참조하려고 하면 프로그램이 충돌할 수 있습니다.
내부적으로 CoCreateInstance 함수는 다양한 기술을 사용하여 개체를 만듭니다. 가장 간단한 경우 레지스트리에서 클래스 식별자를 조회합니다. 레지스트리 진입점은 개체를 구현하는 DLL 또는 EXE를 가리킵니다. CoCreateInstance COM+ 카탈로그 또는 SxS(Side-by-Side) 매니페스트의 정보를 사용할 수도 있습니다. 그럼에도 불구하고 세부 정보는 호출자에게 투명합니다. CoCreateInstance대한 내부 세부 정보에 대한 자세한 내용은 COM 클라이언트 및 서버참조하세요.
사용했던 Shapes 예제는 다소 모순되었으므로 이제 사용자가 파일을 선택할 수 있도록 열기 대화 상자를 표시하는 실제 COM 예제를 살펴보겠습니다.
다음