https://www.youtube.com/watch?v=7FA3PKyg3Vo
컴포넌트 오브젝트 모델(COM)은 마이크로소프트가 개발한 소프트웨어 구성 요소들의 응용 프로그램 이진 인터페이스 표준이다.
응용 프로그램 이진 인터페이스란? 응용 프로그램과 운영 체제 또는 응용 프로그램과 해당 라이브러리, 마지막으로 응용 프로그램의 구성요소 간에서 사용되는 낮은 수준의 인터페이스이다.
ABI는 API와 다르다, API가 소스 코드에서 사용 된다면 ABI는 바이너리에서 호완이 가능하다는 점이 다르다.
<aside> 💡
ABI란 두개의 바이너리 프로그램 모듈 사이의 인터페이스를 말한다.
기계 수준, 이진값 수준에서 인터페이스를 뜻한다. 이진은 Binary로 0과 1을 뜻하는데 컴퓨터에서 가장 low-level을 나타낸다. ABI는 이렇게 바이너리 수준에서의 인터페이스르 뜻한다.
위 정의에서 말하는 모듈은 라이브러리 혹은 Operating System과 사용자에 의해서 실행되는 프로그램을 의미한다.
윈도우 환경에서 내 프로그램을 돌리는 경우를 생각해 볼 수 있다.
그런데 ABI가 호환되어야 프로그램을 돌릴 수 있다. 맥 환경에서 Window 응용 프로그램을 돌릴 수 없는 것이 ABI가 호환되지 않기 때문이다.
ABI와 API의 비교
API는 함수의 argument를 전달하는 순서를 정의한다면,
ABI는 이 arguement를 어떻게 전달할지에 대한 방법을 정의한다. (ex. register, stack 등)
API가 라이브러리의 일부 함수를 정의한다면,
ABI는 코드가 라이브러리 파일 안에 어떻게 저장될 것인지를 정의한다. 이를 통해서 라이브러리를 사용한 어떤 프로그램도 원하는 함수를 실행할 수 있게 된다.
API는 소스코드 레벨에서 호환이 된다면, ABI는 바이너리 수준(이진 수준, 기계 수준)에서 호환이 된다. </aside>
COM을 이용해 개발된 프로그램들은 프로세스간 통신과 동적 오브젝트 생성이 가능하다. 소프트웨어 개발에서는 COM라는 용어를 종종 OLE,OLE 자동화, ActiveX, COM+, DCOM 기술을 포함하는 포괄적 개념으로 사용한다.
다양한 플랫폼에서 COM이 구현되었지만, 주로 마이크로소프트 윈도우에서 사용 된다. COM은 닷넷 프레임워크와 같은 다른 기술로 대체되리라 전망된다.
COM 프로그래머는 COM 컴포넌트들을 사용 하여 소프트웨어를 개발한다. 각각의 COM 컴포넌트들은 클래스 아이디(CLSIDs)로 식별하는데, 클래스 아이디는 전역 고유 식별자(GUID) 형식으로 되어있다. COM 컴포넌트의 기능은 하나 이상의 인터페이스를 통해 노출된다. 컴포넌트에서 지원하는 인터페이스들은 인터페이스 아이디(IIDs)로 식별하는 데 이것 역시 GUID이다.
COM 인터페이스는 C,C++, 비주얼 베이직과 같은 프로그래밍 언어 및 윈도 플랫폼에서 구현된 여러 종류의 스크립트 언어와 바인딩된다. 컴포넌트에 대한 접근은 모두 인터페이스 메소드를 통해 이루어 지는데, 이를 통해 프로세스간(inter-process) 또는 심지어 컴퓨터간(inter-computer) 프로그래밍(후자는 DCOM을 사용한다.) 같은 기법이 허용 된다.
모든 COM 컴포넌트는 표준 IUnknown
인터페이스를 구현한다. 실제 모든 COM 인터페이스는 IUnknown 인터페이스로부터 상속된다. IUnknown 인터페이스는 AddRef(), Release(), QueryInterface() 이렇게 3개의 메서드로 이루어진다.
IUnknown
{
public:
BEGIN_INTERFACE
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject) = 0;
virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0;
virtual ULONG STDMETHODCALLTYPE Release( void) = 0;
template<class Q>
HRESULT
QueryInterface(Q** pp)
{
return QueryInterface(__uuidof(Q), (void **)pp);
}
END_INTERFACE
};