[펌] STDMETHOD ( 이해가 될떄까지 …. )

출처 : http://newly3.tistory.com/20

COM의 매크로이다.


objbase.h에 아래와 같이 선언되어있다.


__cplusplus라는 매크로는 C++을 사용하는 경우 정의되어 있는데


아래 붉은색으로 처리된 부분이 C에 해당하는 코드이다.



#if defined(__cplusplus) && !defined(CINTERFACE)
//#define interface               struct FAR
#define __STRUCT__ struct
#define interface __STRUCT__
#define STDMETHOD(method)       virtual HRESULT STDMETHODCALLTYPE method
#define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method
#define STDMETHODV(method)       virtual HRESULT STDMETHODVCALLTYPE method
#define STDMETHODV_(type,method) virtual type STDMETHODVCALLTYPE method
#define PURE                    = 0
#define THIS_
#define THIS                    void
#define DECLARE_INTERFACE(iface)    interface DECLSPEC_NOVTABLE iface
#define DECLARE_INTERFACE_(iface, baseiface)    interface DECLSPEC_NOVTABLE iface : public baseiface




#if !defined(BEGIN_INTERFACE)
#if defined(_MPPC_)  &&
    ( (defined(_MSC_VER) || defined(__SC__) || defined(__MWERKS__)) &&
    !defined(NO_NULL_VTABLE_ENTRY) )
   #define BEGIN_INTERFACE virtual void a() {}
   #define END_INTERFACE
#else
   #define BEGIN_INTERFACE
   #define END_INTERFACE
#endif
#endif



#else



#define interface               struct



#define STDMETHOD(method)       HRESULT (STDMETHODCALLTYPE * method)
#define STDMETHOD_(type,method) type (STDMETHODCALLTYPE * method)
#define STDMETHODV(method)       HRESULT (STDMETHODVCALLTYPE * method)
#define STDMETHODV_(type,method) type (STDMETHODVCALLTYPE * method)



#if !defined(BEGIN_INTERFACE)
#if defined(_MPPC_)
    #define BEGIN_INTERFACE       void    *b;
    #define END_INTERFACE
#else
    #define BEGIN_INTERFACE
    #define END_INTERFACE
#endif
#endif




STDMETHOD(method)라는 녀석은 virtual HRESULT STDMETHODCALLTYPE method 인데



STDMETHODCALLTYPE는 또 다음과 같이 정의되어있다.



#define STDMETHODCALLTYPE       __stdcall



그래서 STDMETHOD( method ) 라는 녀석은


호출규약 __stdcall Type의 HRESULT를 반환값으로 가지는 Virtual함수 이다.




-번외 : HRESULT :
0~15 비트 : RETURN CODE
16~28 비트: FACILITY
29~30 비트 : R
31 비트 : SEVERITY

SEVERITY(31비트)는 함수의 수행의 성공과 실패를 알려주는 코드다. 를 검사하기 위해서는 다음 예제코드와 같이 SUCCEEDED 혹은 FAILED 매크로를 사용해야 한다.



//SUCCEEDED 경우
    ICalc* pICalc = NULL;

    HRESULT hr = pI->QueryInterface(IID_ICalc, (void**)&pICalc);
    if (SUCCEEDED(hr)) {
        pICalc->Add();
    }
    pICalc->Release();

//FAILED 경우
    HRESULT hr;
    hr = ::CoInitialize(NULL);
    if(FAILED(hr)) {
        AfxMessageBox(“COM 라이브러리를 초기화할 수 없다.”);
        return FALSE;
    }

상태코드 요약 :                    
S_OK : 때때로 Boolean TRUE 값(0X0)으로 S_FALSE와 함께 사용되며 함수가 성공하였음을 의미한다.
NOERROR : S_OK와 동일한 의미이다.
S_FALSE : S_OK와 반대로 Boolean FALSE 값(0X1)으로 함수가 실폐하였음을 의미한다.
E_UNEXPRCTED : 치명적인 실패를 의미한다.
E_NOTIMPL : 멤버 함수에 구현 코드가 포함되어 있지 않다.
E_OUTOFMEMORY : 필요한 메모리를 할당할 수 없음
E_INVALIDARG : 하나 혹은 그 이상의 인자가 타당하지 않음
E_NOINTERFACE : 요청한 인터페이스를 지원하지 않음
E_POINTER : 타당하지 않은 포인터
E_HANDLE : 타당하지 않은 처리
E_ABORT : 작동 중지
E_FAIL : 특정하지 않은 실패
E_ACCESSDENIED : 일반적 접근이 금지된 에러



COM 인터페이스에 소속된 대부분의 함수들은 HRESULT형의 값을 반환하고 있는 데, 멤버 함수들이 이러한 HRESULT형의 값을 반환하는 것은 COM의 규정에 의한 것은 아니다.


그러나 이와 같이 COM 인터페이스에 소속된 대다수 멤버 함수들이 HRESULT형을 반환하면, 클라이언트에게 컴포넌트의 멤버 함수들의 수행과 관련한 상태정보를 일관된 방법으로 반환하게 해주는 결과가 될 것이며, 또한 COM의 하부 시스템에서 발생하는 오류들에 대한 정보를 전달할 수 있게 한다.


즉 COM의 하부 시스템이 아파트먼트(Apartment), 프로세스, 시스템 등의 경계를 가로질러 구성되면, 이러한 하부 시스템은 멤버 함수의 호출에 개입하게 된다. 이때 멤버 함수의 반환 자료형으로 HRESULT형을 사용하면 하부 시스템에서 발생하는 오류들에 대한 정보들을 호출자 즉 클라이언트에게 전달해 줄 수 있다.

댓글 남기기