com기술내막-독서노트(5)
이 장은 DLL을 이용하여 COM 구성 요소(DLL은 구성 요소의 일종의 실현 형식일 뿐)를 실현하고 고객과 구성 요소의 완전한 분리를 초보적으로 실현할 것이다.그러나 이 장은 고객과 구성 요소가 철저하게 분리되지 않았기 때문에 6장과 7장에서는 더욱 유연한 방식을 소개할 것이다.
이 장은 구성 요소를 실행하는 DLL에서CreateInstance 함수를 출력하고 구성 요소를 만들 뿐입니다.
구성 요소의 모든 인터페이스 함수는 IUnknown 인터페이스를 통해 얻을 수 있기 때문에 제3장의CreateInstance 함수는 DLL에서 출력해야 합니다. 구성 요소의 실례를 만들어서 고객에게 IUnknown 인터페이스 바늘을 되돌려줍니다.
DLL을 사용하는 이유:
인터페이스 (예: IX) 는 실제적으로 함수를 가리키는 바늘 목록 (vtbl) 이며, 구성 요소는 vtbl에 메모리를 분배하고, 함수마다 주소를 사용해서 이 표를 초기화합니다.고객이 구성 요소의 인터페이스를 가져왔을 때, 그 인터페이스는 실제적으로 vtbl의 메모리를 가리킨다. DLL은 고객의 호출 프로세스와 같은 메모리 공간을 공유하기 때문에 정확한 vtbl이 분배한 메모리와 각 함수의 주소를 얻을 수 있다.
그중에 한 마디가 인상적이었다."두 프로세스의 바늘은 같은 주소 값을 포함할 수 있지만 실제로는 서로 다른 물리 메모리를 가리킨다."이것은 리눅스에서 포크를 사용하여 하위 프로세스를 만드는 코드를 떠올리게 한다.
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <cstdio>
using namespace std;
int main(void)
{
int iTest;
pid_t pid = fork();
if(pid < 0)
{
perror("fork error");
exit(1);
}
else if(pid == 0)
{
cout<<"main process iTest address: "<<std::hex<<&iTest<<endl;
sleep(3);
exit(0);
}
else
{
cout<<"fork process iTest address: "<<std::hex<<&iTest<<endl;
sleep(3);
exit(0);
}
}
실행 결과
fork process iTest address: 0xbfb464cc main process iTest address: 0xbfb464cc
하위 프로세스에서 부모 프로세스의 데이터 세그먼트를 복사한 것을 볼 수 있지만, 사실 iTest는 서로 다른 물리 메모리 단원에 비추는 것이다
이 장의 프로그램 코드는 다음과 같습니다.
어셈블리 끝
cmpnt.cpp cmpnt.def
//
//cmpnt.cpp
//use: cl /LD cmpnt.cpp cmpnt.def guids.cpp uuid.lib
//
#include <objbase.h>
#include "iface.h"
#include <iostream>
#include <string>
using namespace std;
void trace(string msg)
{
cout<<msg<<endl;
}
class CA:public IX
{
virtual HRESULT __stdcall QueryInterface(const IID &iid, void **ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
virtual void __stdcall Fx()
{
cout<<"CA:Fx"<<endl;
}
public:
CA():m_cRef(0){;}
~CA()
{
trace("Destroy self");
}
private:
long m_cRef;
};
HRESULT CA::QueryInterface(const IID &iid, void **ppv)
{
if(iid == IID_IUnknown)
{
trace("return pointer to iunknown");
*ppv = static_cast<IX*>(this);
}
else if(iid == IID_IX)
{
trace("return pointer to ix");
*ppv = static_cast<IX*>(this);
}
else
{
trace("interface not supported");
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
ULONG CA::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
ULONG CA::Release()
{
if(InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}
extern "C" IUnknown *CreateInstance()
{
IUnknown *pIunknown = static_cast<IUnknown*>(new CA());
pIunknown->AddRef();
return pIunknown;
}
cmpnt.def
;
;compnt module-definition file
;
LIBRARY cmpnt.dll
DESCRIPTION 'cmpnent.dll'
EXPORTS CreateInstance @1 PRIVATE
클라이언트
create.h
//
//create.h
IUnknown *CallCreateInstance(char *name);
create.cpp
//
//create.cpp
//
#include <iostream>
#include <unknwn.h>
using namespace std;
typedef IUnknown* (*CreateFuncPtr)();
IUnknown *CallCreateInstance(char *name)
{
HINSTANCE hInstance = ::LoadLibrary(name);
if(hInstance == NULL)
{
cout<<"callcreateinstance error:can not load compnent"<<endl;
return NULL;
}
CreateFuncPtr CreateInstance = (CreateFuncPtr)::GetProcAddress(hInstance , "CreateInstance");
if(CreateInstance == NULL)
{
cout<<"callcreateinstance error:can not find createinstance func"<<endl;
return NULL;
}
return CreateInstance();
}
client.cpp
//client.cpp
//use: cl client.cpp create.cpp guids.cpp uuid.lib
//
#include <objbase.h>
#include "iface.h"
#include "create.h"
#include <iostream>
#include <string>
using namespace std;
void trace(string msg)
{
cout<<"client: "<<msg<<endl;
}
int main(void)
{
HRESULT hr;
IUnknown *pIunknown = CallCreateInstance("cmpnt.dll");
if(pIunknown == NULL)
{
trace("callcreateinstance failed");
return 1;
}
trace("get interface ix");
IX *pIx = NULL;
hr = pIunknown->QueryInterface(IID_IX, (void**)&pIx);
if(SUCCEEDED(hr))
{
trace("succeeded getting ix");
pIx->Fx();
pIx->Release();
}
else
{
trace("could not get ix");
}
trace("release iunknown interface");
pIunknown->Release();
return 0;
}
클라이언트 및 어셈블리 측 공용 파일
iface.h
#include "objbase.h"
interface IX:IUnknown
{
virtual void __stdcall Fx() = 0;
};
interface IY:IUnknown
{
virtual void __stdcall Fy() = 0;
};
interface IZ:IUnknown
{
virtual void __stdcall Fz() = 0;
};
extern const IID IID_IX
guids.cpp
#include <objbase.h>
// IIDs
// {32bb8320-b41b-11cf-a6bb-0080c7b2d682}
extern const IID IID_IX = {0x32bb8320, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;
// {32bb8321-b41b-11cf-a6bb-0080c7b2d682}
extern const IID IID_IY = {0x32bb8321, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;
// {32bb8322-b41b-11cf-a6bb-0080c7b2d682}
extern const IID IID_IZ = {0x32bb8322, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;
각각 구성 요소와 클라이언트를 컴파일하여 실행합니다
실행 결과
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Access Request, Session and Application in Struts2If we want to use request, Session and application in JSP, what should we do? We can obtain Map type objects such as Req...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.