카테고리 없음

ATL 컴포넌트에 구조체 전달하기

에어버스 2017. 5. 24. 10:22

COM/DCOM 구조체 전달하기 : http://petra.tistory.com/1088

구조체 안의 멤버변수는 idl 지원하는 변수만 사용 가능하다.

idl 파일에 아래 처럼 interface 위 쪽에 구조체(1행~10행)를 선언하고,
구조체의 uuid는 interface uuid의 50974A20으로 시작하는 16진수에 1을 뺀 50974A1F 로 시작하고 나머지는 똑같이 한다.

<ATLXing.idl 소스 일부>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
typedef
[
    uuid(A6562E0F-CE83-4961-8964-30D8DB5E2F4F),
    version(1.0),
]
struct NAMECARD
{
    [helpstring("Name of the variable")]    BSTR     strName;
    [helpstring("Age of the variable")]   LONG     nAge;
} NAMECARD;
 
[
    object,
    uuid(50974A20-EDD4-408C-8232-A84353F90CC5),
    dual,
    nonextensible,
    pointer_default(unique)
]
interface IXing : IDispatch{ // 클래스 추가
    ...
    [id(5)] HRESULT SetNameCard([in] NAMECARD* pNameCard)// 메서드 추가
};    
cs

<Xing.cpp 소스>

SetNameCard 메서드 추가할때 인수의 변수명은 idl 기본 데이터 타입이 아니므로 직접 입력해야 한다.

1
2
3
4
5
6
7
8
9
10
...
 
STDMETHODIMP CXingAPI32TO64::SetNameCard(NAMECARD* pNameCard)
{
    // TODO: 여기에 구현 코드를 추가합니다.
    CString strName(pNameCard->strName); // BSTR to CString 변호
    strName.Format(TEXT("이름:%s, 나이:%d"), strName, pNameCard->nAge);
    AfxMessageBox(strName);
    return S_OK;
}
cs

<클라이언트 소스 일부>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 ...
    struct _NAMECARD
    {
        BSTR strName;
        LONG nAge;
    } N, *LPNAMECARD;
 
    CString tName = "KOREA";
    N.strName = tName.AllocSysString();
    N.nAge = 30;
    LPNAMECARD = &N;    
 
    m_spObject->SetNameCard((NAMECARD*)&N);
 ...
cs

클라이언트의 구조체 역시 idl에서 추가한 구조체 구조(데이터형)와 같아야 한다.

클라이언트에서 SetNameCard를 호출(13행)하면 아래 처럼 DCOM에서 메시지 출력된다.

*** idl 파일에서 구조체의 UUID 없어도 되네... (없이 해보고 안되면 UUID지정하기)

*** idl 파일의 구조체 이름과 Client 의 cpp 파일의 구조체 이름과 반드시 달라야 하고, 내부 구조는 같아야 한다.
만약 같게되면 Client쪽에서 idl 파일이 컴파일(?)되면서 ATL EXE tlh 파일이 생성되므로 이때 이름이 중복되어 컴파일 에러난다. <ATLXing.idl 소스 일부>의 6행 과 <클라이언트 소스 일부>의 2행 참고