1. marshaling의 개념
- COM 서버는 위치 투명성을 지원한다. 즉 COM 클라이언트와 동일 프로세스 내에 있던(in-process server), 동일 머신 타 프로세스로 존재하던지(out-of-process server), remote 머신에 있건(remote server) 상관하지 않는다. 이는 각기 다른 매커니즘을 통한 데이터 통신을 동일한 인터페이스로 이룰 수 있도록 해야한다는 이야기. marshaling은 위의 세 경우 중 프로세스 경계를 넘어 데이터를 전송하는 out-of-process server, remote server를 위한 데이터 전송 매커니즘이다.
2. marshaling의 종류
- standard marshaling, Automation marshaling, custom marshaling의 세 가지가 존재하며, automation marshaling은 프로그래밍 언어간 교차지원을 위한 것이다.
- standard marshaling : MIDL 컴파일러는 IDL(Interface Definition Language) 코드를 컴파일하여 proxy와 stub를 구현한 C 코드를 생성한다. proxy는 COM client에, stub은 COM server에 각각 붙는 양자간 데이터 전송을 위한 메커니즘이다.
- Automation marshaling : automation은 C++ 이외의 언어(주로 Visual Basic 또는 VBScript)로 작성된 클라이언트가 COM 컴포넌트에 접근 가능하도록 하는 기술이다. IDispatch interface를 구현함으로 Automation marshaling을 이룬다. 성능이 standard marshaling에 비해 떨어지는 단점이 존재한다.
- Custom marshaling : Standard marshaling이 적합하지 않은 경우에 사용한다. IMarshal interface 구현을 통해 이루며, 메모리 공유, (참조가 아닌) 값에 의한 marshaling, (비동기 호출 등의 기법을 통해 성능 향상을 위한) Smart proxy, COM threading model 무시 등을 위해 custom marshaling을 사용한다.
less..
IDispatch inteface
- Automation을 이루기 위한 핵심이다. 4개의 메서드를 가지며 Invoke()를 통해 COM Server가 노출하는 메서드의 간접호출을 가능하게 한다. Invoke()의 매개변수 데이터 타입으로는 Automation 호환 데이터 타입, 즉 VARIANT 타입. Visual Basic을 위한 Universal 타입으로서, native 매개변수는 본 타입으로 변환되어 양자간에서 왔다리갔다리한다.
- GetTypeInfoCount()는 COM 개체가 노출하는 TypeInfo 인터페이스의 개수를 반환하고, GetTypeInfo()는 Type Library에서 Type 정보를 반환하며, GetIDsOfNames()는 COM 개체가 노출하는 메서드의 string 형식의 이름을, Invoke()는 매핑된 메서드 번호(DISPID)를 통해 해당 메서드를 호출하는 데 사용한다.
Type Library
- 성능과 tradeoff한 automation의 호환성을 그대로 둔 체, 성능을 더 높이기 위해 나온 구조. 직접적으로 COM 컴포넌트가 노출하는 inteface에(vtable에) 접근 가능하게 하는 메커니즘이다. 이를 위해서는 interface method 매개변수의 타입과 개수를 사전에 알고 있어야 하며, 바로 이들 사항을 Type Library가 제공한다. interface대한 설명(description)을 바이너리 형태-로 나타내는 Type Library는 C++ 헤더 파일의 언어 독립적인 컴파일된 버전으로 봐도 무방하다.
- IDL로 기술된 Type Library를 MIDL 컴파일러가 tlb 확장자의 파일로 생성한다. 생성된 tlb 파일은 종종 COM 컴포넌트가 담긴 dll 또는 exe 파일에 연결(link)된다.
- COM 클라이언트는 COM run-time 라이브러를 통해 registry에서 Type Library를 찾아 접근한다. 따라서 registry에는 해당 Type Library가 등록되어 있어야 한다.
- HKEY_CLASSES_ROOT\TypeLib 하위에 위치하는 Type Library 위치정보는 LIBID로 각 Type Library를 식별하고 해당 엔트리 하위의 win32 엔트리에 해당 Type Library가 있는 파일의 path가 담긴다.
Dual Interface
- C++ 및 비 C++ 기반 COM 클라이언트 모두를 만족시키는 dispatch 인터페이스 구현 방법은 vtable에 IDispatch interface의 Invoke() 메서드 뒤로 해당 COM 컴포넌트가 노출하는 메서드를 위치시키는 것이다. 이를 통해 C++ 클라이언트는 해당 메서드를 직접 호출하고 비 C++ 클라이언트는 Invoke()를 통해 해당 메서드를 호출할 수 있다. 이러한 인터페이스를 가리켜 dual interface라 한다.
- Automation을 이루기 위한 핵심이다. 4개의 메서드를 가지며 Invoke()를 통해 COM Server가 노출하는 메서드의 간접호출을 가능하게 한다. Invoke()의 매개변수 데이터 타입으로는 Automation 호환 데이터 타입, 즉 VARIANT 타입. Visual Basic을 위한 Universal 타입으로서, native 매개변수는 본 타입으로 변환되어 양자간에서 왔다리갔다리한다.
- GetTypeInfoCount()는 COM 개체가 노출하는 TypeInfo 인터페이스의 개수를 반환하고, GetTypeInfo()는 Type Library에서 Type 정보를 반환하며, GetIDsOfNames()는 COM 개체가 노출하는 메서드의 string 형식의 이름을, Invoke()는 매핑된 메서드 번호(DISPID)를 통해 해당 메서드를 호출하는 데 사용한다.
Type Library
- 성능과 tradeoff한 automation의 호환성을 그대로 둔 체, 성능을 더 높이기 위해 나온 구조. 직접적으로 COM 컴포넌트가 노출하는 inteface에(vtable에) 접근 가능하게 하는 메커니즘이다. 이를 위해서는 interface method 매개변수의 타입과 개수를 사전에 알고 있어야 하며, 바로 이들 사항을 Type Library가 제공한다. interface대한 설명(description)을 바이너리 형태-로 나타내는 Type Library는 C++ 헤더 파일의 언어 독립적인 컴파일된 버전으로 봐도 무방하다.
- IDL로 기술된 Type Library를 MIDL 컴파일러가 tlb 확장자의 파일로 생성한다. 생성된 tlb 파일은 종종 COM 컴포넌트가 담긴 dll 또는 exe 파일에 연결(link)된다.
- COM 클라이언트는 COM run-time 라이브러를 통해 registry에서 Type Library를 찾아 접근한다. 따라서 registry에는 해당 Type Library가 등록되어 있어야 한다.
- HKEY_CLASSES_ROOT\TypeLib 하위에 위치하는 Type Library 위치정보는 LIBID로 각 Type Library를 식별하고 해당 엔트리 하위의 win32 엔트리에 해당 Type Library가 있는 파일의 path가 담긴다.
Dual Interface
- C++ 및 비 C++ 기반 COM 클라이언트 모두를 만족시키는 dispatch 인터페이스 구현 방법은 vtable에 IDispatch interface의 Invoke() 메서드 뒤로 해당 COM 컴포넌트가 노출하는 메서드를 위치시키는 것이다. 이를 통해 C++ 클라이언트는 해당 메서드를 직접 호출하고 비 C++ 클라이언트는 Invoke()를 통해 해당 메서드를 호출할 수 있다. 이러한 인터페이스를 가리켜 dual interface라 한다.
reference:
Desktop Applications with Microsoft Visual C++ 6.0 MCSD Training Kit,
MSDN