ATL COM
bro, Jo kyung min , nst
오후 12:44 2000-05-12
asp & VB in ATL C++
=================================================================
asp 서포트 하기
ATL 프로젝트를 연 후 , New ATL Object을 하되, ActiveX Server Component
로 하게 되면 기본적으로 Response객체나 Request객체의 포인터를
기본 자료로 갖게 된다.
기본 Simple Object에 asp 기능 서포트 하기
자신의 인터페이스 프록시 클래스헤더에
class ATL_NO_VTABLE CTestCom :
public CComObjectRootEx<CComMultiThreadModel>,
:
이런식이라면
#include <asptlb.h> // Active Server Pages Definitions
:
class ATL_NO_VTABLE CTestCom :
public CComObjectRootEx<CComMultiThreadModel>,
:
asp에 관한 맴버 메소드와 자료
// ITestCom
public:
//Active Server Pages Methods
STDMETHOD(OnStartPage)(IUnknown* IUnk);
STDMETHOD(OnEndPage)();
private:
CComPtr<IRequest> m_piRequest; //Request Object
CComPtr<IResponse> m_piResponse; //Response Object
CComPtr<ISessionObject> m_piSession; //Session Object
CComPtr<IServer> m_piServer; //Server Object
CComPtr<IApplicationObject> m_piApplication; //Application Object
BOOL m_bOnStartPageCalled; //OnStartPage successful?
};
하고… 실제 구현은
STDMETHODIMP CTestCom::OnStartPage (IUnknown* pUnk)
{
if(!pUnk)
return E_POINTER;
CComPtr<IScriptingContext> spContext;
HRESULT hr;
// Get the IScriptingContext Interface
hr = pUnk->QueryInterface(IID_IScriptingContext, (void **)&spContext);
if(FAILED(hr))
return hr;
// Get Request Object Pointer
hr = spContext->get_Request(&m_piRequest);
if(FAILED(hr))
{
spContext.Release();
return hr;
}
// Get Response Object Pointer
hr = spContext->get_Response(&m_piResponse);
if(FAILED(hr))
{
m_piRequest.Release();
return hr;
}
// Get Server Object Pointer
hr = spContext->get_Server(&m_piServer);
if(FAILED(hr))
{
m_piRequest.Release();
m_piResponse.Release();
return hr;
}
// Get Session Object Pointer
hr = spContext->get_Session(&m_piSession);
if(FAILED(hr))
{
m_piRequest.Release();
m_piResponse.Release();
m_piServer.Release();
return hr;
}
// Get Application Object Pointer
hr = spContext->get_Application(&m_piApplication);
if(FAILED(hr))
{
m_piRequest.Release();
m_piResponse.Release();
m_piServer.Release();
m_piSession.Release();
return hr;
}
m_bOnStartPageCalled = TRUE;
return S_OK;
}
STDMETHODIMP CTestCom::OnEndPage ()
{
m_bOnStartPageCalled = FALSE;
// Release all interfaces
m_piRequest.Release();
m_piResponse.Release();
m_piServer.Release();
m_piSession.Release();
m_piApplication.Release();
return S_OK;
}
이렇게 하면 된다.
마지막으로 idl도 넣어야 한다.
interface ITestCom : IDispatch
{
//Standard Server Side Component Methods
HRESULT OnStartPage([in] IUnknown* piUnk);
HRESULT OnEndPage();
그렇다면 asp 서버 페이지 객체로 되어 버리면 VB에서 쓸수 없는가?
아니다. 쓸수 있다.
Method 하나를 만들어보자.
STDMETHODIMP CTestCom::Method(VARIANT varString)
{
// TODO: Add your implementation code here
// VB나 asp나 공통으로 실행되는 부분
USES_CONVERSION;
char* pszString = W2A(varString.bstrVal);
::MessageBox(NULL, pszString, “asdf”, MB_OK );
if( m_piRequest ) // 만일 리퀘스트 객체가 있다면
{ // 아래는 asp의 경우의 코드
VARIANT varRes;
varRes.vt = VT_BSTR;
varRes.bstrVal = ::SysAllocString(L”hahahah”);
// 웹페이지에 hahahah를 찍어라.
m_piResponse->Write( varRes );
}
else
{
// 객체 생성에 실패했으므로 그냥 VB같은 클라이언트에서
실행되는 코드로 가정된다.
}
return S_OK;
}
오후 1:25 2000-05-25
조경민 웹 페이지(asp/Script)에서 넘어오는 문자열 잡아 내기
—————————————————————
STDMETHODIMP CChartGen::fnDrawChart(VARIANT sType, int nPosX, int nPosY, int nPosX2, int nPosY2)
{
char* pszPlugName;
USES_CONVERSION;
if( sType.vt == VT_BSTR)
{
pszPlugName = W2A(sType.bstrVal);
}
else if( sType.vt & (VT_BYREF|VT_VARIANT) )
{
pszPlugName = W2A( sType.pvarVal->bstrVal );
}
else
{
MessageBox(NULL, “문자열이 아닙니다.”,”에러”,MB_OK);
}
// pszPlugName에 인자로 넘어온 문자열이 들어 있다.
|
오후 3:39 2000-05-03
조경민 USES_COMVERSION
====================================================
BSTR test( BSTR bstrVal )
{
USES_CONVERSION;
char* pszVal;
W2A(bstrVal,pszVal);
하면 pszVal 안에 BSTR문자열값이 들어간다.
BSTR bstrCopy;
A2W(pszVal,bstrCopy);
하면 pszVal값이 bstrCopy에 들어간다. SysAlloc된 상태
사용후
SysFreeString(bstrCopy);해야 함
BSTR bstrRet;
A2W(pszVal,bstrRet);
return bstrRet; // ATL컴포넌트 메소드가 BSTR리턴시
} // SysAlloc후 리턴한다.
// VC Client에서 SysFreeString해야함
// VB Client에서는 알아서 프리시킴
BSTR<->char* 컨버팅이 간편한
USES_CONVERSION을 쓰려면…
1. ATL Project
-> 그냥 쓸수 있다.
2. MFC Project
-> #include <comdef.h>
#include <afxpriv.h>
3. Win32 Dll Project
#include <comdef.h>
#include <CRTDBG.H>
#include <atlconv.h>
를 하면 된다.
COM에서 WideChar와 AnsiChar 바꾸는 매크로
VARIANT에 문자열 넣기
// com support class
#include <comdef.h>
#include <AFXPRIV.H> // USES_CONVERSION 이 정의된 곳
USES_CONVERSION;
VARIANT var;
VariantInit(&var);
var.vt = VT_BSTR;
var.bstrVal = SysAllocString(A2W(“하하하하하”));
*웹페이지에서는 문자열은 VARIANT를 써야 한다.
다음은 asp서포트 상태에서 BSTR과 char*사이의 변환이다.
if( m_piServer )
{
USES_CONVERSION;
BSTR bstrLogicPath, bstrPhysicPath;
bstrLogicPath = SysAllocString(A2W(“/NstChart”));
m_piServer->MapPath( bstrLogicPath, &bstrPhysicPath)
SysFreeString( bstrLogicPath );
char* pszPhysicPath = W2A(bstrPhysicPath);
m_plgManager->fnSetPlugPath( pszPhysicPath );
}
——————————————————————
참고 테크니컬 노트
TN059: Using MFC MBCS/Unicode Conversion Macros
This note describes how to use the macros for MBCS/Unicode conversion which are defined in AFXPRIV.H. These macros are most useful if your application deals directly with the OLE API or for some reason, often needs to convert between Unicode and MBCS.
Overview
In MFC 3.x, a special DLL was used (MFCANS32.DLL) to automatically convert between Unicode and MBCS when OLE interfaces were called. This DLL was an almost transparent layer that allowed OLE applications to be written as if the OLE APIs and interfaces were MBCS, even though they are always Unicode (except on the Macintosh). While this layer was convenient and allowed applications to be quickly ported from Win16 to Win32 (MFC, Microsoft Word, Microsoft Excel, and VBA, are just some of the Microsoft applications that used this technology), it also had a sometimes significant performance hit. For this reason, MFC 4.x does not use this DLL and instead talks directly to the Unicode OLE interfaces. To do this, MFC needs to convert to Unicode to MBCS when making a call to an OLE interface, and often needs to convert to MBCS from Unicode when implementing an OLE interface. In order to handle this efficiently and easily, a number of macros were created to make this conversion easier.
One of the biggest hurdles of creating such a set of macros is memory allocation. Because the strings cannot be converted in place, new memory to hold the converted results must be allocated. This could have been done with code similar to the following:
// we want to convert an MBCS string in lpszA
int nLen = MultiByteToWideChar(CP_ACP, 0,lpszA, -1, NULL, NULL);
LPWSTR lpszW = new WCHAR[nLen];
MultiByteToWideChar(CP_ACP, 0,
lpszA, -1, lpszW, nLen);
// use it to call OLE here
pI->SomeFunctionThatNeedsUnicode(lpszW);
// free the string
delete[] lpszW;
This approach as a number of problems. The main problem is that it is a lot of code to write, test, and debug. Something that was a simple function call, is now much more complex. In addition, there is a significant runtime overhead in doing so. Memory has to be allocated on the heap and freed each time a conversion is done. Finally, the code above would need to have appropriate #ifdefs added for Unicode and Macintosh builds (which don’t require this conversion to take place).
The solution we came up with is to create some macros which 1) mask the difference between the various platforms, and 2) use an efficient memory allocation scheme, and 3) are easy to insert into the existing source code. Here is an example of one of the definitions:
#define A2W(lpa) (
((LPCSTR)lpa == NULL) ? NULL : (
_convert = (strlen(lpa)+1),
AfxA2WHelper((LPWSTR) alloca(_convert*2),
lpa, _convert)
)
)
Using this macro instead of the code above and things are much simpler:
// use it to call OLE here
USES_CONVERSION;
pI->SomeFunctionThatNeedsUnicode(T2OLE(lpszA));
There are extra calls where conversion is necessary, but using the macros is simple and effective.
The implementation of each macro uses the _alloca() function to allocate memory from the stack instead of the heap. Allocating memory from the stack is much faster than allocating memory on the heap, and the memory is automatically freed when the function is exited. In addition, the macros avoid calling MultiByteToWideChar (or WideCharToMultiByte) more than one time. This is done by allocating a little bit more memory than is necessary. We know that an MBC will convert into at most one WCHAR and that for each WCHAR we will have a maximum of two MBC bytes. By allocating a little more than necessary, but always enough to handle the conversion the second call second call to the conversion function is avoided. The call to the helper function AfxA2Whelper reduces the number of argument pushes that must be done in order to perform the conversion (this results in smaller code, than if it called MultiByteToWideChar directly).
In order to for the macros to have space to store the a temporary length, it is necessary to declare a local variable called _convert that does this in each function that uses the conversion macros. This is done by invoking the USES_CONVERSION macro as seen above in the example.
There are both generic conversion macros and OLE specific macros. These two different macro sets are discussed below. All of the macros reside in AFXPRIV.H.
Generic Conversion Macros
The generic conversion macros form the underlying mechanism. The macro example and implementation shown in the previous section, A2W, is one such “generic” macro. It has no relation to OLE specifically. The set of generic macros is listed below:
A2CW (LPCSTR) -> (LPCWSTR)
A2W (LPCSTR) -> (LPWSTR)
W2CA (LPCWSTR) -> (LPCSTR)
W2A (LPCWSTR) -> (LPSTR)
Besides doing text conversions, there are also macros and helper functions for converting TEXTMETRIC, DEVMODE, BSTR, and OLE allocated strings. These macros are beyond the scope of this discussion ? refer to AFXPRIV.H for more information on those macros.
OLE Conversion Macros
The OLE conversion macros are designed specifically for handling functions which expect OLESTR characters. If you examine the OLE headers you will see many references to LPCOLESTR and OLECHAR. These types are used to refer to the type of characters used in OLE interfaces in a way that is not specific to the platform. OLECHAR maps to char in Win16 and Macintosh platforms and WCHAR in Win32.
In order to keep the number of #ifdef directives in the MFC code to a minimum we have a similar macro for each conversion that where OLE strings are involved. The following macros are the most commonly used:
T2COLE (LPCTSTR) -> (LPCOLESTR)
T2OLE (LPCTSTR) -> (LPOLESTR)
OLE2CT (LPCOLESTR) -> (LPCTSTR)
OLE2T (LPCOLESTR) -> (LPCSTR)
Again there are similar macros for doing TEXTMETRIC, DEVMODE, BSTR, and OLE allocated strings. Refer to AFXPRIV.H for more information.
Other Considerations
Don’t use the macros in a tight loop. For example, you do NOT want to write the following kind of code:
void BadIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
for (int ii = 0; ii < 10000; ii++)
pI->SomeMethod(ii, T2COLE(lpsz));
}
The code above could result in allocating megabytes of memory on the stack depending on what the contents of the string lpsz is! It also takes time to convert the string for each iteration of the loop. Instead move such constant conversions out of the loop:
void MuchBetterIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
LPCOLESTR lpszT = T2COLE(lpsz);
for (int ii = 0; ii < 10000; ii++)
pI->SomeMethod(ii, lpszT);
}
If the string is not constant, then encapsulate the method call into a function. This will allow the conversion buffer to be freed each time. For example:
void CallSomeMethod(int ii, LPCTSTR lpsz)
{
USES_CONVERSION;
pI->SomeMethod(ii, T2COLE(lpsz));
}
void MuchBetterIterateCode2(LPCTSTR* lpszArray)
{
for (int ii = 0; ii < 10000; ii++)
CallSomeMethod(ii, lpszArray[ii]);
}
Never return the result of one of the macros, unless the return value implies making a copy of the data before the return. For example, this code is bad:
LPTSTR BadConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR lpsz = NULL;
pI->GetFileName(&lpsz);
LPTSTR lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
return lpszT; // bad! returning alloca memory
}
The code above could be fixed by changing the return value to something which copies the value:
CString BetterConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR lpsz = NULL;
pI->GetFileName(&lpsz);
LPTSTR lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
return lpszT; // CString makes copy
}
The macros are easy to use and easy to insert into your code, but as you can tell from the caveats above, you need to be careful when using them.
오후 2:38 2000-05-03
조경민
ATL COM to WWW
===================================================================
먼저 ATL 프로젝트로 프로그램을 만든다.
( 이때 Support MTS를 하면 MTS 함수를 불러다 쓸수 있다.
물론 서포트를 안해도 MTS에 올릴 수 있다. )
MTS에 등록하기
먼저 시작 -> 관리도구 -> 서비스 구성요소 를 들어간다.
그리고 콘솔루트/구성요소서비스/컴퓨터/내컴퓨터/COM+응용프로그램
을 들어가서 오른클릭 새로 만들기를 해서 빈 문서를 만든다.
이름 : NSTChart
그리고 NSTChart에서 오른클릭후 구성요소에서
새 구성요소를 설치합니다.
를 선택해서 내가 만든 com dll을 등록한다.
( 이때 com dll이 c:projecttestcomreleasetestcom.dll 처럼
꼭 system32 디렉토리에 없어도 된다. )
*만일 MTS에 안올리고 인터넷 서비스에서 관리하면 꼭 system32에
놔야만 하고 만일 새롭게 갱신된 dll로 엎으려고 하면 캐슁되어서
서비스를 내려야 한다. 서비스 잘 안내려가서 부팅을 계속 해야 한다*
그리고 regsvr32 c:projecttestcomreleasetestcom.dll 를 해서
등록을 하면 된다.
사용은 아래 처름 asp로 하면 되고.
만일 새롭게 갱신된 testcom.dll을 다시 갱신하고 싶으면
컴파일 하기 전에 ( 컴파일후 바로 파일 바뀌기가 되므로 )
구성요소 서비스에서 NSTChart에서 오른클릭후 시스템 종료를 하면
모듈이 내려가서 갱신 할 수도 있고 편리하다.
다음은 asp 페이지다.
<HTML>
<BODY>
Chart ATL Component Test Site
<HR>
<%
Response.Write “===================================”
Dim obj
Dim obj2
Dim sOutURL
On Error Resume Next
Set obj = Server.CreateObject(“NSTChart.ChartGen”)
If Err.Number <> 0 Then
Response.Write “에러 발생”+Err.Description
End If
obj.m_nWidth = 100
obj.m_nHeight = 200
obj.fnDrawChart “NSTPieChart”, 0, 0, 100, 200
sOutURL = obj.fnGenerateImage()
Response.Write “생성 성공”+ cstr(obj.m_nHeight)
Response.Write “<IMG SRC=”+sOutURL+”>”
Set obj = Nothing
%>
<HR>
</BODY>
</HTML>
오전 7:41 99-12-18
오후 6:33 00-02-04 Added. ( 이벤트 부분, 적용사례 )
ATL 조금 하기 조경민 ( bro@shinbiro.com )
==========================================================
ATL COM Object 만들기
———————————-
New/ ATL COM Project로 연다. TestATL이라는 프로젝트명으로한다.
그냥 InProcess DLL로 할 것이므로 dll을 선택한다.
( – Excutable EXE : Out of Process COM 구현시
– Service EXE : NT에서 쓰는 서비스 처럼 NT start up시
백그라운드로 돌 COM 구현시 )
– MFC Support : CString 같은 MFC 쓰고 싶으면 체크한다.
Finish를 하여 프로젝트를 만든다.
내가 구상하는 Object에 대한 Interface 추가
– 워크스페이스에서 클래스뷰로 가서 프로젝트에 오른클릭을
하여 New ATL Object을 한다.
그리고 Simple ATL Object을 선택하고 Simple이라는 이름으로 하고
속성탭은 Both, Dual, Agrregate No , Connection Point Yes
를 한다.
Dual – 생성시 idl에 현 인터페이스가 상속될 것은 IDispatch로
VTable이 생김으로 인터페이스의 늦은 바인딩의 이점이 있으나
IDispatch::Invoke를 해야 함으로 많이 느리다.
Custum – IUnknown으로 직접 상속을 받게 되는 인터페이스로
빠른 코드를 만들고 싶을때 쓰면 된다.
Agrregation : COM 통합을 할 것인가를 결정한다.
Connection Point : 이벤트 Fire 기능을 갖을 것인가를 결정한다.
=> 생성되는 인터페이스는 Simple 클래스로 idl에는
interface ISimple : IDispatch로 되어 있을것이다.
현재 클래스뷰 구조
[-] TestSimple classes
[-] -O _ISimpleEvents : ISimple의 이벤트 인터페이스
[-] CSimple : ISimple의 구현 클래스 ( 프록시클래스)
+ -O ISimple : ISimple 인터페이스
+ CSimple() : CSimple의 생성자 메소드
[+] CTestSimpleApp : App
[-] ISimple : ISimple 인터페이스(위와 같은 놈)
[+] Globals
Add Method/Property to Interface
———————————-
클래스뷰의 ISimple에서 오른클릭후 Add Method나 Add Property
를 함으로써 인터페이스에 대한 메소드, 프로퍼티를 줄수 있다.
메소드 구현하기 만일 Method라는 것을 만들고 싶다면
ISimple에서 오른 클릭후 Add Method후
리턴값 : HRESULT ( 바꿀수 없다 )
함수명 : Method
파라미터 : [in] long val
한후 CSimple안의 ISimple에서 Method를 두번 클릭하면 실제 구현하는
메소드를 볼 수 있다.
즉 CSimple이 ISimple의 Method를 구현해 주고 있는 것이다.
STDMETHODIMP CSimple::Method(long val)
{
// 아래 코드는 MFC 서포트로 처음에 세팅했다면 들어가는 코드이다
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// TODO: Add your implementation code here
return S_OK;
}
Event Fire 기능 주기
——————–
이미 생성시 Connection Point를 체크했기 때문에 idl에는
다음과 같은 것이 더 추가된다.
dispinterface _ISimpleEvents
실제로 이를 구현하는 클래스를 만들려면
그냥 CSimple에서 오른클릭하면 Implements Connnectiion Point이라는
메뉴가 나오지 않는다. 일딴 컴파일을 해서 성공을 한 후
CSimple에서 오른클릭후 Implements Connnectiion Point를 한후
원하는 이벤트 인터페이스를 선택한후 OK를 누르면 ( _ISimpleEvents )
CProxy_ISimpleEvents라는 클래스가 생겨 구현하는 클래스가 생긴다.
만일 Fire_Clikin( long x )를 구현 하고 싶다면
먼저 ISimpleEvents에서 오른클릭후 Add Method를
void Clikin( long x )를 만들어준다.
리턴값 : void
함수명 : Clickin
파라미터 : [in] long x
그러나 CProxy_ISimpleEvents는 바뀌지 않았따.
( 이말은 이벤트 메세드를 _ISimpleEvents에 생성을 했을때 각 메소드
들이 CProxy_ISimpleEvents에서도 똑같이 보여야만 한다는 말이다 )
-_- 웃긴것은 다시 컴파일을 한 후 ( 계속 그렇게 해야 한다 )
ISimple 오른클릭후 Implements Connnection Point
를 해주어야지 반영된다는 것이다.
반영되면 그것으로 CProxy_ISimpleEvents::Fire_Clikin(long x)
가 생기게 된다. 이 때 메소드의 내용이 이미 구현이 되어진다.
( 이 부분이 바로 실제 인터페이스의 내용을 구현하는 것이다 )
실제 Fire를 하기
CSimple의 코드내에서
Fire_Clickin(1);
이렇게 쓰게 되면 그때 이벤트가 생기게 된다.
—————————————————————–
이벤트를 캐취하자. ( in VB )
‘ 일딴 아래처럼 이벤트를 갖은 타입 라이브러리의 인터페이스를
‘ 설정한다.
Private WithEvents obj As TESTSIMPLELib.Simple
‘ ~~~~~~~~~~
Private Sub Command1_Click()
Set obj = New TESTCOMMLib.Simple ‘ 실 객체를 할당한다.
obj.Method (1) ‘ 메소드를 호출한다.
End Sub
‘ 이벤트를 캐취하는 이벤트 메서드 정의
Private Sub obj_Event(ByVal val As Long)
MsgBox “이벤트가 뜹니다.”
Set obj = Nothing ‘ 이제는 더이상 이벤트를 받지 않는다.
‘ 또한 obj에 할당된 객체도 해체된다.
End Sub
이렇게 캐취해 낼수 있다.
다음은 MSDN에서 발췌한 WithEvents에 대한 제한 사항이다.
WithEvents 변수의 제한 사항
다음 제한 사항에 유의하여 WithEvents 변수를 사용해야 합니다.
WithEvents 변수는 포괄적 개체 변수가 될 수 없습니다. 즉, As Object로
선언할 수 없고 변수를 선언할 때 클래스 이름을 지정해야 합니다.
WithEvents 변수를 As New로 선언할 수 없습니다. 이벤트 원본 개체는
명시적으로 작성되고 WithEvents 변수에 할당되어야 합니다.
표준 모듈에서 WithEvents 변수를 선언할 수 없습니다. 클래스 모듈,
폼 모듈, 클래스를 정의하는 기타 모듈 등에서만 선언할 수 있습니다.
WithEvents 변수의 배열을 작성할 수 없습니다.
———————————————————————-
ATL COM 이벤트는 VC에서 어떻게 다루어야 하는지 아직 모른다.
VC에서 ATL COM 객체를 가져다가 쓰기
// You need to point this header file to the directory
// you placed the Simple_ATL project
#include “..Simple_ATLSimple_ATL.h”
#include <iostream.h>
// Copy the following from the Simple_ATL_i.c file
// from the Simple_ATL project directory
const IID IID_IFirst_ATL =
{0xC8F6E230,0x2672,0x11D3,{0xA8,0xA8,0x00,0x10,0x5A,0xA9,0x43,0xDF}};
const CLSID CLSID_First_ATL =
{0x970599E0,0x2673,0x11D3,{0xA8,0xA8,0x00,0x10,0x5A,0xA9,0x43,0xDF}};
void main(void)
{
// Declare and HRESULT and a pointer to the Simple_ATL interface
HRESULT hr;
IFirst_ATL *IFirstATL;
// Now we will intilize COM
hr = CoInitialize(0);
// Use the SUCCEEDED macro and see if we can get a pointer
// to the interface
if(SUCCEEDED(hr))
{
hr = CoCreateInstance( CLSID_First_ATL, NULL,
CLSCTX_INPROC_SERVER,
IID_IFirst_ATL, (void**) &IFirstATL);
// If we succeeded then call the AddNumbers method, if it failed
// then display an appropriate message to the user.
if(SUCCEEDED(hr))
{
long ReturnValue;
hr = IFirstATL->AddNumbers(5, 7, &ReturnValue);
cout << “The answer for 5 + 7 is: ” << ReturnValue << endl;
hr = IFirstATL->Release();
}
else
{
cout << “CoCreateInstance Failed.” << endl;
}
}
// Uninitialize COM
CoUninitialize();
}
쉽게 하기 ( IID나 CLSID 몰라도 하기 )
——————————————————————————
대신 실행하면 나오는 TestSimple.tlb파일( 형식 라이브러리)이 필요하다.
이 형식 라이브러리 파일을 자기 프로젝트 디렉토리에 놓기만 하고
StdAfx.h 파일에 다음처럼 기입한다.
#include “atlbase.h”
#import “TestComm.tlb” no_namespace named_guids
그러면 자동으로 ISimplePtr같은 포인터를 그냥 쓸수 있다. (IID도 자동으로 로드됨)
dlg.h에서 인터페이스 변수를 선언
ISimplePtr m_SimplePtr;
HRESULT hr;
hr = CoInitialize(0);
if(SUCCEEDED(hr))
{
hr = ::CoCreateInstance(CLSID_Simple,
NULL,
CLSCTX_INPROC_SERVER,
IID_ISimple,
(LPVOID*)&m_SimplePtr);
if(FAILED(hr))
{
TRACE(“생성 불가n”);
return FALSE;
}
}
를 한후
m_SimplePtr->Method(1);
로 사용 하면 된다.