반응형
사용자 삽입 이미지

이 소스로는 아직까지는 main 에서 LoadLibrary 를 사용하여 DLL의 이름을 로드해서 쓰는 DLL 의잔재가 남아있다.. 다음번에 해결 하도록 하고 일단 아래 소스로 개념을 이해하자.

( 레지스트리에 DLL의 CLSID를 등록한것을 이용해서 DLL의 경로명을 가져와 사용할 수 있도록 다음번엔)


Component DLL ------------------------ DLL 로 제작.

- Interface 선언  -> interface.h

- IID                -> interface_i.h

- CoClass (실제 동작 클래스) -> Component.cpp

- CreateInstance()          -> Component.cpp


component.def 파일도 만들어서 프로젝트에 같이 넣어준다.



Client -------------------------------- 사용하는 플그램

interface.h 와

interface_i.h 를 인쿨르드 하여 사용.




============= 실제 소스 ========= DLL ===================

CInside.cpp

#include <iostream.h>
#include <objbase.h>

#include "interface.h"
#include "interface_i.c"

extern const IID IID_ISetVal;
extern const IID IID_ICalcu;


class CInsideCom : public ISetVal, ICalcu
{
 int x,y;

 virtual HRESULT __stdcall QueryInterface(REFIID iid, void** ppv);
 virtual ULONG __stdcall AddRef();
 virtual ULONG __stdcall Release();

 virtual void __stdcall SetValue(int x1, int y1)
 {
  x = x1;
  y = y1;
 }
 virtual int __stdcall Sum() {
  return x+y;
 }
 virtual int __stdcall Sub() {
  return x-y;
 }
public:
 CInsideCom() : m_cRef(0) {}
 ~CInsideCom() {
  cout << "CInsideCom is destroyed by itself." << endl;
 }
private:
 long m_cRef;
};
HRESULT __stdcall CInsideCom::QueryInterface(REFIID iid, void** ppv)
{
 if(iid == IID_IUnknown) {
  *ppv = static_cast<ISetVal*>(this);
 }
 else if(iid == IID_ISetVal) {
  *ppv = static_cast<ISetVal*>(this);
 }
 else if(iid == IID_ICalcu) {
  *ppv = static_cast<ICalcu*>(this);
 }
 else {
  cout << "QueryInterface : interface not supported" << endl;
  *ppv = NULL;
  return E_NOINTERFACE;
 }
 static_cast<IUnknown*>(*ppv)->AddRef();
 return S_OK;
}
ULONG __stdcall CInsideCom::AddRef()
{
 cout << "m_cRef = " << m_cRef+1 << endl;
 return InterlockedIncrement(&m_cRef);
}

ULONG __stdcall CInsideCom::Release()
{
 cout << "m_cRef = " << m_cRef-1 << endl;
 if(InterlockedDecrement(&m_cRef) == 0 ) {
  delete this;
  return 0;
 }
 return m_cRef;
}

// #define STDAPI_(type)   EXTERN_C type STDAPICALLTYPE C함수로 동작. C++에서 이렇게 안하면 함수이름바뀜.
STDAPI_(IUnknown*) CreateInstance()
{
 IUnknown *pI = static_cast<ISetVal*>(new CInsideCom);
 pI->AddRef();
 return pI;
}


interface_i.c

#pragma once
#include <objbase.h>

// {7D1DA4D3-2DD8-4317-937D-157BF19DE48C}
static const IID IID_ISetVal =
{ 0x7d1da4d3, 0x2dd8, 0x4317, { 0x93, 0x7d, 0x15, 0x7b, 0xf1, 0x9d, 0xe4, 0x8c } };

// {1BA9514E-9303-4c4d-948A-D1EAA0932A82}
static const IID IID_ICalcu =
{ 0x1ba9514e, 0x9303, 0x4c4d, { 0x94, 0x8a, 0xd1, 0xea, 0xa0, 0x93, 0x2a, 0x82 } };

interface.h

#pragma once
#include <objbase.h>

interface ISetVal : IUnknown
{
 virtual void __stdcall SetValue(int , int) = 0;
};

interface ICalcu : IUnknown
{
 virtual int __stdcall Sum() = 0;
 virtual int __stdcall Sub() = 0;
};


 

Cinside.def

; module-definition file....  이것이 주석의 개념이다.
LIBRARY  CInsideComDll.dll        
DESCRIPTION 'InsideCom‘      
EXPORTS  
   CreateInstance    @1 PRIVATE  


============== 컴포넌트 사용 Console 프로젝트파일 ================

dll파일과 interface.h interface_i.c 파일 복사해옴.

//InsideComClient.cpp
#include <iostream.h>
#include <objbase.h>
#include "interface.h"
#include "interface_i.c"

HINSTANCE hc;
IUnknown* CreateInstance(char* name)
{
 IUnknown* (*pFunc)();
 hc = ::LoadLibrary(name);
 if(hc == NULL) {
  cout << "LoadLibrary() failed with error" << endl;
  return NULL;
 }
 pFunc = (IUnknown * (*)()) ::GetProcAddress(hc,"CreateInstance");
 if(pFunc == NULL) {
  cout << "GetProcAddress() failed with Error" << endl;
  return NULL;
 }
 return pFunc(); //객체 생성
}
void main(void)
{
 HRESULT hr;
 int x1, y1;
 
 cout << "Please enter an integer x1 and y1" << endl;
 cin >> x1 >> y1;
 IUnknown* pIUnknown=NULL;
 pIUnknown = CreateInstance("CInsideComDll.dll");
 if(pIUnknown == NULL) {
  cout << "CreateInstance() failed with error" << endl;
  return;
 }
 ISetVal* pISetVal=NULL;
 hr = pIUnknown->QueryInterface(IID_ISetVal,(void**)&pISetVal);
 if(SUCCEEDED(hr)) {
  pISetVal->SetValue(x1,y1);
  pISetVal->Release();
 }
 
 ICalcu* pICalcu = NULL;
 hr = pIUnknown->QueryInterface(IID_ICalcu,(void**)&pICalcu);
 if(SUCCEEDED(hr)) {
  cout << "x1 + y1 = " << pICalcu->Sum() << endl;
  cout << "x1 - y1 = " << pICalcu->Sub() << endl;
  pICalcu->Release();
 }
 pIUnknown->Release();
 FreeLibrary(hc);
}

반응형

+ Recent posts