1. 자동화
- VB나 ASP같은 스크립트기반 언어에서는 COM객체의 인터페이스에 직접 접근할 수 없다. 하지만 자동화를 통해 COM객체를 사용할 수 있다. 자동화를 통하면 마샬링을 위한 프록시/스텁 구현도 필요가 없다. 하지만, 자동화의 단점은 수행속도, 사용가능한 데이터형의 제한이 있다. 이를 위해 MS에서는 자동화와 기존의 커스텀 인터페이스를 모두 지원하는 이중 인터페이스를 제안함.
2. IDispatch인터페이스
- IUnknown에서 파생됨. GetTypeInfoCount, GetTypeInfo, GetIDsOfNames, Invoke등의 4개의 메소드가 있다.
- 다음 VB의 예
dim obj As Object set obj = CreateObject(ProgID) obj.Prop = propVal obj.Method |
> VB의 CreateObject를 하면, COM라이브러리의 CLSIDFromProgID함수를 이용하여 CLSID를 가져온 후, CoCreateInstance를 호출해 자동화 객체를 생성한 후에, IDispatch인터페이스를 받아와서 obj에 저장.
1) GetIDsOfNames : 매개변수에 지정되는 메소드나 속성이름에 대응하는 DISPID를 반환. DISPID는 메소드나 속성을 구별하는 ID.
프로토타입
HRESULT STDMETHODCALLTYPE GetIDsOfNames( REFIID riid, // ID_NULL LPOLESTR *rsgzNames, // 메소드, 속성명 UINT cNames, // 개수 LCID lcid, // 로케일 정보 DISPID *rgDispId); // 반환된 DISPID값 |
- cNames는 거의1. (보통 한번에 하나의 속성, 메소드에 대한 DISPID를 구한다.)
2) Invoke : 위에서 구해온 DISPID를 가지고, 이 함수를 호출하여, DISPID에 대응하는 함수를 호출.
프로토타입
HRESULT STDMETHODCALLTYPE Invoke( DISPID dispIdMember, // DISPIP REFIID riid, // ID_NULL LCID lcid, // 로케일 정보 WORD wFlags, // 플래그 DISPPARAMS *pDispParams, // 매개변수 정보 VARIANT *pVarResult, // 리턴된 결과 EXCEPTINFO *pExcepInfo, // 예외상황 정보 UINT *puArgErr); // 에러 매개변수 인덱스 |
- 플래그 : Invoke에서는 해당 호출이 메소드인지(DISPATHCH_METHOD), 속성을 저장하는 함수인지(DISPATCH_PROPERTYPUT), 속성을 읽는 함수인지(DISPATCH_PROPERTYGET), 레퍼런스로 속성을 저장하는 함수인지 (DISPATCH_PROPERTYPUTREF)를 지정하는데 사용한다.
- DISPPARAM : 내부에 호출되는 함수에 전달하여 줄, 매개변수 저장됨
typedef struct tagDISPPARAMS{ VARIANTARG *rgvarg; //매개변수 배열 DISPID* rgdispidNamedArgs; // 이름을 가지는 매개변수의 DISPID배열 UINT cArgs; // 매개변수 갯수 UINT cNamedArgs; // 이름을 가지는 매개변수의 갯수 } DISPPARAMS; |
- 에러정보 구하기 : 에러 정보는 아래 구조체에 담겨서 반환된다.
typedef struct tagEXCEPTINFO{ WORD wCode; //에러코드 WORD wReserved; BSTR bstrSource; // 예외발생소스 BSTR bstrDescription; // 예외 설명 BSTR bstrHelpFile; // 도움말 경로 DWORD dwContextHelp; // 도움말 컨텍스트 ULONG pvReserved; ULONG pfnDeferredFillin; //구조체를 채울 함수 SCODE scode; // 리턴값 } EXCEPTINFO; |
> 위 구조체를 Invoke의 인자로 넘겨주면된다. 아니면 IErrorInfo 인터페이스를 받아와서 처리해도 됨.
3. late binding vs early binding
- 자동화 컨트롤러가 자동화객체의 속성이나 메소드와 결합하는 시간이 런타임(late)인지, 컴파일타임(early)인지에 따라 구분됨. late binding이 더 느리나, 동적으로 자동화객체의 기능을 결정할 수 있다.
-> 각 속성과 메소드에 대응하는 DISPID는 고정되고 이것은 형식 라이브러리에 저장된다. 컴파일 타임에 이를 읽어오면 GetIDsOfNames를 호출하지 않아도 된다. -> 더 빠르다. 이것은 ID binding으로 early binding의 한 종류
4. VARIANT 데이터형
- VARIANT구조체는 다른 데이터형을 가지는 큰 공용체로 구성되어있다.
- VariantChangeType() : VARIANT인스턴스의 데이터를 다른데이터로 바꿀때 사용
5. BSTR데이터형
- wide char문자열 포인터. 제일 앞에 문자수가 들어간다. 그래서 SysAllocString()으로 BSTR을 할당해 주어야 정상적으로 사용가능하다. 그리고, BSTR할당 후에는 SysFreeString()으로 해제하여 줄 것.
6. SAFEARRAY데이터형
- 배열 범위에 대한 정보를 가지고 있음
typedef struct tagSAFEARRAY{ USHORT cDims; //배열의 차원 수 USHORT fFeatures; // 플래그 ULONG cbElements; // 배열 요소의 갯수 ULONG cLocks; // lock 카운트 PVOID pvData; // 배열의 데이터 포인터 SAFEARRAYBOUND rgsabound[1]; //각 배열 차원 바운드 } SAFEARRAY;
typedef struct tagSAFEARRAYBOUND{ ULONG cElements; // 배열 요소 수 LONG lLbound; // 배열 하위 바운드 } SAFEARRAYBOUND; |
댓글