오후 1:13 2002-09-28
조경민 bro@shinbiro.com
원하는 인터페이스 가져다 쓰기
=======================================================

요약.
원하는 인터페이스의 idl을 midl 컴파일러를 통해 형식 라이브러리(tlb)
를 얻어내어 이를 #import 하여 쉽게 COM을 억세스 하도록 한다.

먼저, 원하는 인터페이스의 idl을 얻어내야 한다.
idl 파일이 직접 있다면 이를 이용하고, 없다면
VC++의 툴인 OLE/COM Object Viewer를 연 후,
원하는 COM 오브젝을 찾아낸다.

예)
All Objects 트리 노드에서 Messenger Object (Messenger API)를 선택한다.
오른 클릭 후 'View Type Information'을 선택한다.
그러면 해당 오브젝의 구조를 나타내는 ITypeLib Viewer가 뜨는데 여기서
File/ Save as를 하여 Messenger.idl 로 저장한다. 파일명은 마음대로..
이렇게 하면 IDL을 얻어 올 수 있다.

일딴 IDL이 마련되면 이를 이용하여 형식 라이브러리 파일을 만들자.
midl /mktyplib203 <idl파일명> 을 넣으면 되며 아래는 그 예이다.

D:\>midl /mktyplib203 messenger.idl

Microsoft (R) MIDL Compiler Version 5.01.0164
Copyright (c) Microsoft Corp 1991-1997. All rights reserved.
Processing .\messenger.idl
messenger.idl
Processing C:\Program Files\Microsoft Visual Studio\VC98\include\oaidl.idl
oaidl.idl
Processing C:\Program Files\Microsoft Visual Studio\VC98\include\objidl.idl
objidl.idl
Processing C:\Program Files\Microsoft Visual Studio\VC98\include\unknwn.idl
unknwn.idl
Processing C:\Program Files\Microsoft Visual Studio\VC98\include\wtypes.idl
wtypes.idl

이렇게 하면 messenger.tlb를 얻을 수 있다.

일딴 형식라이브러리 정보를 갖고 있는 com 또는 exe( out of process com )또는
tlb 파일들을 얻었으면 이를 VC++ #import 를 이용하여 쉽게 사용 할 수 있게
하는 스마트 포인터를 쓸 수 있다.

다음은 예이다.
stdafx.h 에

#import "messenger.tlb" named_guids
using namespace MessengerAPI;

를 추가한다.
named_guids는 필수로 넣어주며, 만일 namespace가 충돌이 일어난다면
no_namespace를 이용하거나, rename을 이용하여 이름을 바꾼다.
실제로 MSN 프로그래밍시 msmsgs.exe라는 MSN 본체 COMEXE에는 두개의
API 셋이 존재한다.
msmsgs.exe 메인으로 있는 Messenger 1.0 과
msmsgs.exe\3 에 있는 Messenger API가 그것이다.
그런데 둘다 #import 하여 아래처럼 얻어오면

// Messenger 1.0은 메인 노출 라이브러리라 그냥 exe에서 바로 import한다.
#import "C:\Program Files\Messenger\msmsgs.exe" named_guids
// Messenger API 라이브러리는 위에서의 예를 행하여 형식라이브러리랄 추출
// 해 와서 쓰고 있는 중이다.
#import "messenger.tlb" named_guids

그런데 위의 것 (1.0)의 namespace는 Messenger이며 아래의 것은 인터페이스
클래스 명에 Messenger라는 것이 있어 같은 심볼이 있어 충돌이 일어나게 된다.

다음은 Messenger1.0의 형식라이브러리헤더인 msmsgs.tlh의 윗부분이다.
-----
// Created by Microsoft (R) C/C++ Compiler Version 12.00.8447.0 (dc7ba1f5).
//
// msmsgs.tlh
//
// C++ source equivalent of Win32 type library C:\Program Files\Messenger\msmsgs.exe
// compiler-generated file created 09/28/02 at 11:19:27 - DO NOT EDIT!

#pragma once
#pragma pack(push, 8)

#include <comdef.h>

namespace Messenger { <- 이름이 Messenger
------

그리고 Messenger.tlh에 있는 클래스명이다.
--------
// Created by Microsoft (R) C/C++ Compiler Version 12.00.8447.0 (ab16ee58).
//
// messenger.tlh
//
// C++ source equivalent of Win32 type library messenger.tlb
// compiler-generated file created 09/28/02 at 13:12:28 - DO NOT EDIT!

#pragma once
#pragma pack(push, 8)

#include <comdef.h>

namespace MessengerAPI {

       :
/* dual interface */ IMessengerGroup;
struct /* coclass */ Messenger; <- 이름이 같아서 충돌나게 된다.
------
이럴때는 위의 Messenger 네임스페이스를 살짝 바꾸면 된다.

결국 아래처럼 하면 된다. using 부분은 그냥 쉽게 쓰기 위해서 넣은 것이다.
#import "C:\Program Files\Messenger\msmsgs.exe" named_guids rename("Messenger","msn")
using namespace msn;

#import "messenger.tlb" named_guids
using namespace MessengerAPI;

이렇게 하면
IMsgrObjectPtr                m_MsgObject;
이런 식으로 스마트 포인터를 쓸 수 있으며,

IMessenger의 메소드인
HRESULT get_MyContacts(
        IDispatch ** ppMContacts
);
를 원래는 아래처럼 사용해야 하는 메소드이지만,
  IMessengerGroups* Groups;
  IMessenger2* msg;
     :
  IDispatch* lpGroups;
  msg->get_MyGroups( &lpGroups ); // 프로퍼티도 그냥 raw 함수식으로 불편
  Groups = lpGroups;
  lpGroups->Release();

Import로 얻어온 스마트 포인터로는
  IMessengerGroupsPtr Groups;
  IMessenger2Ptr msg;

  Groups = msg->MyGroups; // 이렇게 쓸 수 있다. 간단하지 않은가?

프로퍼티 메소드에 대한 쉬운 접근 맴버 변수를 추가로 만들어주기때문에
쓰기가 더욱 쉽게 된다. (마치 VB에서 인터페이스의 프로퍼티를 접근할때처럼)


--------------------------
참고.. 형식 라이브러리 import를 하지 않고 MSN API 를 쓰려면
MSN API용 라이브러리를 얻은 후 아래처럼 해야 한다.
( 불편하기 그지 없다. )

#include "msgruaid.h"
#include "msgrua.h"
#pragma comment(lib,"msgrguid.lib")

_COM_SMARTPTR_TYPEDEF(IMessenger, __uuidof(IMessenger));
_COM_SMARTPTR_TYPEDEF(IMessenger2, __uuidof(IMessenger2)););
_COM_SMARTPTR_TYPEDEF(IMessenger3, __uuidof(IMessenger3)););
:

이 때 역시 프로퍼티 접근이 불편하긴 마찬가지다.

+ Recent posts