DLLÀÇ Å¬·¡½º »ç¿ë

ÇÁ·Î±×·¥À» ©¶§ DLL·Î ¸¸µé¸é ¸Þ¸ð¸®°¡ Àý¾à µÇ±â ¶§¹®¿¡ DLLÀ» »ç¿ë ÇÒ±î? ±×·¸Áö ¾Ê´Ù. ¿î¿µÃ¼Á¦³ª ÄÄÆ÷³ÍÆ®¸¦ ¸¸µå´Â°Ô ¾Æ´Ï¸é ¸Þ¸ð¸® Àý¾à µÇ´Â °æ¿ì´Â ¾ø´Ù.
DLLÀ» »ç¿ëÇÏ´Â ÃÖ´ëÀÇ ÀÌÁ¡Àº ¸ðµâÈ­°¡ ¾Æ´Ò±î ÇÑ´Ù. DLL·Î ¸¸µé°Ô µÇ¸é, ¼Ò½º°£ÀÇ Á¾¼Ó¼ºÀÌ ¸¹ÀÌ ÁÙ¾îµç´Ù.

DLL¿¡´Â ¹¬½ÃÀû ¸µÅ©¿Í ¸í½ÃÀû ¸µÅ©°¡ ÀÖ´Ù.
¹¬½ÃÀû ¸µÅ©´Â ÇÁ·Î±×·¥ÀÌ ½ÇÇà µÊ°ú µ¿½Ã¿¡ DLLÀÌ ·ÎµùµÈ´Ù. ¸í½ÃÀû ¸µÅ©´Â ¿ì¸®°¡ ¿øÇÏ´Â ½Ã±â¿¡ ·Îµù°ú ÇØÁ¦¸¦ ÇÒ ¼ö ÀÖ´Ù.

1. ¹¬½ÃÀû ¸µÅ© (dll_test1.zip)

DLLÀ» ¸¸µå´Âµ¥ »ç¿ëµÈ ÆÄÀÏÀº dllserver.h dllserver.cpp ÆÄÀÏÀÌ´Ù.

*.dllÀ» ¸¸µé¶§´Â __declspec(dllexport) ¼±¾ðÇØ ¿ÜºÎ·Î ³ëÃâ½Ãų Ŭ·¡½º³ª ÇÔ¼ö¸¦ ÁöÁ¤ÇÑ´Ù.
Ŭ·¡½º CDllServer¸¦ ¿ÜºÎ·Î ¾Ë·ÁÁÖ±â À§ÇØ, ºñÁê¾ó ½ºÆ©µð¿ÀÀÇ "±¸¼º ¼Ó¼º  - C/C++ - Àü󸮱â"¿¡ DLL_EXPORT¸¦
¼±¾ðÇØÁÖ´Â ¹æ¹ýÀÌ Ã¹ ¹ø°°í , µÎ ¹ø°°¡ dllserver.cppÀÇ ¿¹¿Í °°ÀÌ #define DLL_EXPORT¸¦ ³Ö´Â ¹æ¹ýÀÌ ÀÖ´Ù.

__declspec(dllexport)¸¦ ¼±¾ðÇÏÁö ¾ÊÀ¸¸é ´ÙÀ½ ¿¡·¯°¡ ¶á´Ù.

f:\work\dll_test\dll_server\dllserver.cpp(5) : warning C4273: 'CDllServer::CDllServer' : dll ¸µÅ©°¡ ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù.

 ~~~~~~~~~~~~~~~~~~~~~  Áß·«  ~~~~~~~~~~~~~~~~~~~~~~~~~~~

¼Ó¼º - ±¸¼º ¼Ó¼º - ºôµå À̺¥Æ® - ºôµå ÈÄ À̺¥Æ® - ¸í·ÉÁÙ¿¡ ´ÙÀ½ ¸í·ÉÀ» Ãß°¡ÇÏ¿© ºôµå°¡ ³¡³­ÈÄ dll_server.dllÀ»
ÀÚµ¿À¸·Î º¹»çÇϵµ·Ï ÇÑ´Ù.

copy  "$(SolutionDir)$(OutDir)\$(TargetFileName)"  "..\dll_client\Debug\$(TargetFileName)"

 

1)DLL ¼Ò½º

//dllserver.h

#ifndef        __DLLSERVER_H

#define        __DLLSERVER_H

 

#ifdef DLL_EXPORT

   #define DLL_DECLSPEC  __declspec(dllexport)   

#else

   #define DLL_DECLSPEC  __declspec(dllimport)   

#endif

 

 

class DLL_DECLSPEC    CDllServer

{

public:

    CDllServer();

    ~CDllServer();

    int        Add(int num);

    int        Sub(int num);

    int        GetNum();

 

private:

    int        m_iSum;

};

 

#endif

 

//dllserver.cpp

#define DLL_EXPORT

#include "dllserver.h"

 

CDllServer::CDllServer()

{

    m_iSum = 0;

}

 

//~~~~~~~~~~~~~~~~~~~~~~~~~~  Áß      ·« ~~~~~~~~~~~~~~~~~~~~~~~~~~

 

 

 

2) DLLÀ» È£ÃâÇÏ´Â ÇÁ·Î±×·¥

dllserver.h ÆÄÀÏÀÌ Æ÷Ç﵃ ¶§ DLL_EXPORT ¼±¾ðÀÌ ¾ÈµÇ¾î Àֱ⠶§¹®¿¡, DLL_DECLSPECÀº __declspec(dllimport)·Î º¯È¯µÈ´Ù.

ÇÔ¼ö ¼±¾ð¿¡¼­ __declspec(dllimport)Àº »ç¿ëÇÏÁö ¾Ê¾Æµµ µÇÁö¸¸,  ÀÌ Å°¿öµå¸¦ »ç¿ëÇϸé ÄÄÆÄÀÏ·¯¿¡¼­ º¸´Ù È¿À²ÀûÀÎ
Äڵ带 »ý¼ºÇÒ ¼ö ÀÖ½À´Ï´Ù.
±×·¯³ª ½ÇÇà ÆÄÀÏÀÌ DLLÀÇ °ø¿ë µ¥ÀÌÅÍ ±âÈ£ ¹× °³Ã¼¿¡ ¾×¼¼½ºÇÒ ¼ö ÀÖµµ·Ï ÇÏ·Á¸é __declspec(dllimport)À» »ç¿ëÇØ¾ß ÇÑ´Ù.
¹¬½ÃÀû ¸µÅ©¿¡¼­ Ŭ·¡½º¸¦ »ç¿ëÇÏ´Â °æ¿ì, __declspec(dllimport)¸¦ »ç¿ëÇÏÁö ¾Ê´õ¶óµµ Äڵ带 »ý¼º ÇÒ ¼ö ÀÖ´Ù.

¹¬½ÃÀû ¸µÅ©´Â *.lib ÆÄÀÏÀ» Æ÷ÇÔ ½ÃÄÑ¾ß ÇÑ´Ù. ¶óÀ̺귯¸® ÆÄÀÏÀ» Æ÷ÇÔÇÏ´Â ¹æ¹ýÀº ¼¼°¡Áö°¡ ÀÖ´Ù.

¶óÀ̺귯¸® ÆÄÀÏ Æ÷ÇÔ ½ÃÅ°´Â ¹æ¹ý

. DLLÀÇ lib ÆÄÀÏÀ» ÇÁ·ÎÁ§Æ® ±¸¼º ¼Ó¼º¿¡ Á÷Á¢ Æ÷ÇÔ½ÃÅ°´Â ¹æ¹ý.

. DLL ÇÁ·ÎÁ§Æ®¿Í DLLÀ» È£ÃâÇÏ´Â ÇÁ·ÎÁ§Æ®¸¦ °°Àº ¼Ö·ç¼Ç¿¡ ÀÖÀ¸¸é ÀÚµ¿À¸·Î ¸µÅ©µÈ´Ù.

. #pragma comment(lib, "libÀ̸§")  ¸¦ ¼Ò½º Äڵ忡 Æ÷ÇÔ ½ÃÅ°´Â ¹æ¹ý.

 

±×¸®°í ºôµå.....

//dll_client.cpp

#include <iostream>

#include "../dll_server/dllserver.h"

 

void main()

{

    CDllServer test;

    test.Add(1);

    test.Add(2);

    test.Add(3);

    test.Sub(5);

 

    std::cout << "Value is " << test.GetNum() << std::endl;

    getchar();

}

 

2. ¸í½ÃÀû ¸µÅ© dll_test2.zip

¾Æ·¡´Â ÇÔ¼ö È£Ã⠱Ծ࿡ µû¸¥ ½ºÅà Á¤¸® ¹æ½ÄÀÌ´Ù.

È£Ãâ ±Ô¾à ÆĶó¹ÌÅÍ ½º  Åà Ư  Â¡
__cdecl ¿À¸¥ÂÊ --> ¿ÞÂÊ È£ÃâÇÑ °÷ °¡º¯ ÀÎÀÚ Áö¿ø
__fastcall ¿À¸¥ÂÊ --> ¿ÞÂÊ È£Ãâ ´çÇÑ °÷ ÆĶó¹ÌÅÍ µÎ °³¸¦ ecx, edx¸¦ ÅëÇؼ­ Àü´ÞÇϱ⠶§¹®¿¡ µÎ °³ ÀÌÇÏÀÇ ÀÎÀÚ¸¦ °¡Áø ÇÔ¼ö¿¡ ´ëÇؼ­ ºü¸§
__stdcall ¿À¸¥ÂÊ --> ¿ÞÂÊ È£Ãâ ´çÇÑ °÷ Windows Ç¥ÁØ È£Ãâ ±Ô¾à
__thiscall ¿À¸¥ÂÊ --> ¿ÞÂÊ È£Ãâ ´çÇÑ °÷ ecx¸¦ ÅëÇؼ­ this Æ÷ÀÎÅ͸¦ Àü´ÞÇÔ

¸í½ÃÀû ¸µÅ©´Â *.lib ÆÄÀÏ ¾øÀÌ LoadLibrary(), GetProcAddress(), FreeLibrary()¸¦ ÀÌ¿ëÇØ
DLLÀ» ·Îµù, ÇÔ¼ö ÁÖ¼Ò±¸ÇÏ¿© ½ÇÇà, DLL ÇØÁ¦¼øÀ¸·Î ½ÇÇàÇÑ´Ù.

Ŭ·¡½ºÀÇ ¸â¹ö ÇÔ¼ö´Â C·Î ÀÛ¼ºµÈ ÇÔ¼ö¿Í´Â ´Þ¸® name manglingÀÌ µÇ±â ¶§¹®¿¡ DUMPBIN À¯Æ¿¸®Æ¼·Î export µÈ
ÇÔ¼öÀ̸§À¸·Î GetProcAddress()¸¦ ½ÇÇàÇÑ´Ù.

Ŭ·¡½º ¸â¹ö ÇÔ¼ö ½ÇÇà ¹æ¹ý

Çì´õÆÄÀÏ°ú DLL ÆÄÀϸ¸ ÀÌ¿ëÇØ ¸â¹ö ÇÔ¼ö¸¦ È£ÃâÇÏ´Â ¹æ¹ýÀº ¼¼°¡Áö´Ù.

    //ù¹ø° ¹æ¹ý: ¸â¹ö ÇÔ¼ö Sub¸¦ °¡»óÇÔ¼ö·Î ¹Ù²Û´Ù.

    pTest->Sub(5);

 

    //µÎ¹ø° ¹æ¹ý

    *************  __thiscall ¿¹¾à¾î°¡ Àû¿ëµÇ´Â °æ¿ì    *****************

    int (__thiscall *pSub)(int) = (int (__thiscall *)(int) )GetProcAddress(hInst, "?Sub@CDllServer@@QAEHH@Z");

    pSub(pTest, 5);

 

    //¼¼¹ø° ¹æ¹ý (ÇÔ¼ö¸¦ ÅëÇÏ¿© Ŭ·¡½ºÀÇ ÀνºÅϽº Àü´Þ)

    int (*pFnSub)(CDllServer*, int)  = (int (*)(CDllServer*, int)) GetProcAddress(hInst, "Sub"); //¸í½ÃÀû   

    pFnSub(pTest, 5);

1. ¸â¹ö ÇÔ¼ö ¾Õ¿¡ virtualÀ» ¼±¾ðÇÏ¿© °¡»óÇÔ¼ö·Î ¼±¾ðÇÑ´Ù.
°¡»ó ÇÔ¼ö·Î ¼±¾ðÇÒ °æ¿ì Ưº°ÇÏ°Ô ÇØÁÙ ÀÏÀÌ ¾ø´Ù.

2. __thiscallÀ» »ç¿ëÇÏ´Â ¹æ¹ý
Ŭ·¡½ºÀÇ ¸â¹ö ÇÔ¼ö´Â __thiscallÀ» »ç¿ëÇÑ´Ù. ÇÏÁö¸¸ .Net 2003¿¡¼­ ÀÌ ¿¹¾à¾î´Â Áö¿øµÇÁö ¾Ê´Â´Ù.
.Net 2005³ª .Net 2008¿¡¼­ Áö¿ø µÇ´ÂÁö´Â À߸𸣰ڴÙ.

CDllServer Ŭ·¡½ºÀÇ Sub ¸â¹ö ÇÔ¼ö ¿øÇüÀº int Sub(int num) ÀÌ´Ù.
µÎ±ºµ¥ÀÇ __thiscall È£Ã⠺κÐÀÌ Àִµ¥, º¹ÀâÇØ º¸ÀÌÁö¸¸ ¿øÇü°ú ºñ½ÁÇÏ´Ù.
GetProcAddress()ÇÔ¼ö¾ÈÀÇ "?Sub@CDllServer@@QAEHH@Z" À̸§Àº DUMPBIN À¯Æ¿¸®Æ¼³ª ¸µÅ© ¿¡·¯°¡ ¶ß¸é Ãâ·ÂµÈ´Ù.

ÇÔ¼ö ÁÖ¼Ò¸¦ ±¸Çؼ­ ½ÇÇà ÇÒ ¶§´Â "ÇÔ¼öÁÖ¼Ò( ¿ÀºêÁ§Æ® ÁÖ¼Ò, ÇÔ¼ö·Î ³Ñ±æÀÎÀÚ)" ½ÄÀ¸·Î ¸â¹ö ÇÔ¼ö¸¦ ½ÇÇàÇÑ´Ù.

3. ÇÔ¼ö¸¦ ÅëÇÏ¿© Ŭ·¡½ºÀÇ ÀνºÅϽº Àü´Þ

°¡»ó ÇÔ¼ö¸¦ »ç¿ëÇÏÁö ¾ÊÀ» ¶§, »ç¿ëÇÒ ¼ö ÀÖ´Â ¹æ¹ýÀ¸·Î DLLÀÇ Å¬·¡½º¿¡ Àü¿ªÇÔ¼ö¸¦ ¸¸µé¾î Ŭ·¡½ºÀÇ ¿ÀºêÁ§Æ® ÁÖ¼Ò¿Í
ÀÎÀÚ¸¦ ³Ñ±ä´Ù.

extern "C" DLL_DECLSPEC  int Sub(CDllServer * pObj, int num)

{

    return pObj->Sub(num);

}

 

DLL ¸ðµâ¿¡¼­ CreateCDllServer()¸¦ ÅëÇØ ¿ÀºêÁ§Æ®¸¦ »ý¼º ÇÏ¿´´Ù¸é, ¿ÀºêÁ§Æ® ÇØÁ¦ÀÇ °æ¿ìµµ DLL¾È¿¡ ¸¸µå´Â °ÍÀÌ ¹Ù¶÷Á÷ÇÏ´Ù.

¿ÀºêÁ§Æ® ÇØÁ¦ ===> fpRelease(pTest)

//DLL ¸ðµâÀÇ ¿ÀºêÁ§Æ® ÇØÁ¦ ÇÔ¼ö

extern "C" DLL_DECLSPEC    void ReleaseCDllServer(CDllServer *& pObj)

{

    delete pObj;

    pObj = NULL;

}

C++ÀÌ ³ª¿À±â ÀÌÀü¿¡´Â ÂüÁ¶°¡ ¾ø¾ú±â ¶§¹®¿¡ ÀÌÁß Æ÷ÀÎÅ͸¦ ÀÌ¿ëÇØ ¸µÅ©µå ¸®½ºÆ®¸¦ ±¸Çö Çß¾ú´Ù.
ÀÌÁß Æ÷ÀÎÅ͸¦ Æ÷ÀÎÅÍ ÂüÁ¶·Î º¯È¯Çϸé È¥¶õÀÌ ´ú »ý±æ°ÍÀÌ´Ù.


ÂüÁ¶:

Game Programming gems2 Á¤º¸¹®È­»ç ¹ø¿ªÆÇ
http://www.jiniya.net/lecture/techbox/callconv.html  (½Å¿µÁø´ÔÀÇ ÇÔ¼ö È£Ãâ ±Ô¾à)

__declspec(dllimport)À» »ç¿ëÇÏ¿© ÀÀ¿ë ÇÁ·Î±×·¥À¸·Î °¡Á®¿À±â(MSDN)