제 11 장동적연결라이브러리 11.1 DLL 의링크 11.2 DLL 의종류 실습 11-1 Implicit 링킹을통한정규 DLL 달력만들기 실습 11-2 Explicit 링킹을통한정규 DLL 달력만들기 실습 11-3 확장 DLL 을통한주민등록번호조회 프로그램만들기
DLL(Dynamic Linked Library) DLL 이란? 동적연결라이브러리 프로그램내부에라이브러리가있는것이아니라따로독립적으로실행가능한파일 필요시에로드할수있는라이브러리
DLL(Dynamic Linked Library) DLL 의장점 실행파일의크기를줄일수있다 메모리를효율적으로사용할수있다. 재사용이가능하다. 커다란프로젝트를여러개의작은프로젝트로나누어작성할수있다. 새로운함수나기능추가를다시링크하지않고처리할수있다.
DLL(Dynamic Linked Library) DLL 의단점 실행파일이작아지는대신배포해야할파일의수가증가한다. 프로젝트의복잡성을증가시킬수있다. 버전관리에더욱신경을써야한다.
DLL 링크 Implicit 링킹 프로그램이시작되면서 DLL 을바로로드하는방법 Implicit 링킹을위해필요한파일 실질적으로프로그램이실행될때로드되는 DLL 파일 (*.DLL) 컴파일할때설정해주는함수명이들어있는헤더파일 (*.H) 링크할때메인프로그램에빈함수를설정하는 LIB 파일 (*.LIB)
DLL 링크 Implicit 링크에서 LIB 함수가필요한이유 메인프로그램을컴파일하고링크할때 DLL 안에들어있는함수들은메인프로그램에어느것과도링크되어있지않아실행파일을만들때에러가난다. LIB 파일에서함수를가상함수로만들어그것을 0 으로설정해주는함수가있어야링크시에러가나지않는다.
DLL 링크 Implicit 링크사용방법 ( 로드하는프로젝트와 DLL 프로젝트가별도인경우 ) 링크옵션에서사용할 DLL 파일의임포트라이브러리 (*.LIB) 를추가한다. 사용할 DLL 파일의임포트라이브러리 (*.LIB) 를프로젝트디렉터리에복사한다. 헤더파일을포함한다.
DLL 링크 Explicit 링크 Implicit 링크처럼세가지파일이필요없이단순하게 DLL 을이용하여로드하는방법 이방법으로 DLL 을로드할경우세개의함수를이용한다. LoadLibrary() 함수 GetProcAddress() 함수 FreeLibrary() 함수
DLL 링크 Explicit 링크사용방법 먼저사용하고자하는함수에대한타입을선언해야한다 Typedef int(*calenderfunc)(int num); LoadLibrary() 함수를이용하여프로그램내에서사용하고자하는 DLL 을메모리에로드한다. HINSTANCE hdll hdll = LoadLibrary( Execise.dll );
DLL 링크 Explicit 링크사용방법 ( 계속 ) DLL 에서사용할함수의메모리번지를알아오고그값을포인터로받는다. 이때익스포트되는함수의인자와반환형이일치되어야한다. CalenderFunc lpcalenderfunc; lpcalenderfunc = (CalenderFunc) GetProcAddress(hDll, Calender ); 원하는함수를호출한후더이상필요하지않을경우 FreeLibrary() 함수를이용하여메모리에서해제한다. FreeLibrary(hDll);
DLL 의종류 정규 DLL (Regular DLL) Win32 프로그램환경으로설정 표준 C 형식의인터페이스사용 함수를호출할때클래스형태의함수를호출하는것이아니라 C 형태의함수를호출 MFC 를사용하지않는비쥬얼베이직, 델파이등과도원활하게연결할수있는범용적인 DLL 이다.
DLL 의종류 정규 DLL 작성법 현재함수가 DLL 외부에서사용할수있도록함수를선언한다. extern C _desclspec(dllexport) void Calender() 함수내용을코딩할때 _desclspec(dllexport) 를함수앞에쓰고구현한다. 이렇게하고컴파일하면 DLL 파일과 LIB 파일이생성된다.
DLL 의종류 정규 DLL 사용법 함수를호출하려면다음과같이함수선언시설정해주면된다. 선언할때함수명과같아야하고 dllimport 로바꾸어주면된다. extern C _desclspec(dllimport) void Calender() DLL 함수를호출해사용하면된다.
DLL 의종류 확장 DLL (Extension DLL) MFC 전용 DLL 메인프로그램에서 DLL 을호출할때클래스로호출할수있고, MFC 구조와원활하게연결될수있는구조체로되어있다. 쉽게말해서 DLL 로생각하지않고그냥클래스사용하듯이사용하면된다. 클래스자체를 DLL 로만들고 MFC 프로그램과연결만하려면확장 DLL 을사용하는것이좋다.
DLL 의종류 확장 DLL 작성법 클래스명선언앞에단순히 AFX_EXT_CLASS 를설정한다. Class AFX_EXT_CLASS CCalenderDlg : public Cdialog 이렇게하고컴파일하면 DLL 파일과 LIB 파일이생성된다.
DLL 의종류 확장 DLL 사용법 Implicit 링킹을이용하여 LIB 파일을링크시킨다. DLL 클래스헤더파일을포함시킨다. 일반적인클래스를사용하듯이확정 DLL 클래스를사용하면된다.
실습 11-1 정규 DLL 만들기 (Implicit 링킹 ) 년도와달을넘겨주면해당되는달력이반환되는 DLL 함수를만들고메인프로그램에서이 DLL 을 Implicit 링크해보도록한다.
실습 11-1 정규 DLL 만들기 (Implicit 링킹 ) 실행
실습 11-1 프로그램작성순서 1) DLL 함수를호출할프로젝트를생성한다. Dialog Based 프로젝트를생성한다. 2) MFC DLL 프로젝트를생성한다. 첫단계에서 공유 MFC DLL 을사용하는기본 DLL 을선택한다. 3) cpp 함수에외부에서사용할함수를만든다. DLL 외부에서호출하여사용할함수와필요한변수들을선언하고초기화시킨다. extern C _desclspec(dllexport) 함수명
실습 11-1 프로그램작성순서 4) 대화상자폼에컨트롤을배치하고속성을설정한다. Edit Control, Spin Control, Combo Box 설정 5) 각컨트롤들을멤버변수에연결한다. OnDraw( ) 함수에서문자열을출력한다. 6) DLL 을호출할준비를한다. 프로젝트속성페이지에서 CalenderDll 프로젝트를참조로추가한다.
실습 11-1 프로그램작성순서 7) 각컨트롤을초기화시키고클래스에필요한멤버변수를추가한다. 8) 각컨트롤들의이벤트핸들러함수를생성한다. 9) 달력을화면에출력한다. OnPaint() 함수에서코팅해준다. 10) 프로그램을실행시킨다.
실습 11-2 정규 DLL 만들기 (Explicit 링킹 ) 년도와달을넘겨주면해당되는달력이반환되는 DLL 함수를만들고메인프로그램에서이 DLL 을 Explicit 링크해보도록한다.
실습 11-2 프로그램작성순서 1) 실습 11-1 의프로젝트를연다. 실습 11-1 프로젝트폴더를복사하여이름을변경하고프로젝트파일을연다. 2) Explicit 링킹으로 DLL 을읽어서사용한다. Implicit 링킹으로읽어왔던부분을삭제한다. OnPaint() 함수에 DLL 을읽어오는코드를추가한다. 3) 프로젝트를실행시킨다.
실습 11-3 확장 DLL 만들기 주민등록변호를입력받고확장 DLL 을이용하여주민등록번호가올바른지검사하고나이와성별을출력하는프로젝트이다.
실습 11-3 프로그램작성순서 1) DLL 함수를호출할프로젝트를생성한다. Dialog Based 프로젝트를생성한다. 2) MFC DLL 프로젝트를생성한다. 첫단계에서 MFC 확장 DLL 을선택한다. 3) 생성된 IDCheckDll 프로젝트에클래스를추가한다. 4) 외부에서주민등록번호조회에필요한함수를추가한다.
실습 11-3 5) 폼에컨트롤을배치하고속성을설정한다. Edit Control, Static Text, Button 설정 6) DLL 을호출할수있도록설정한다. 프로젝트속성페이지에서 IDCheckDll 프로젝트를참조로추가한다. [ 속성페이지 ] 대화상자에서 [ 구성속성 ]-[C/C++]- [ 일반 ] 탭을선택하여다음과같이 CJumin 클래스의헤더파일을참조하기위해디렉터리를추가한다. 7) [ 조회 ] 버튼에대해메시지핸들러함수를만든다. 8) 프로그램을실행시킨다.
연습 11-1 확장 DLL 만들기 2 차방정식근을구하는확장 DLL 을작성하고확장 DLL 을이용하여이차방정식의근을구하는프로그램을작성한다.
void CExercise11_1Dlg::OnClickedButtonCalcRoot() { CString strtemp; double fa,fb,fc, fdet; GetDlgItemText(IDC_EDIT_A,strTemp); fa = _wtof(strtemp); if (fa==0) AfxMessageBox(_T(" 첫번째계수는 0이될수없습니다.")); SetDlgItemText(IDC_EDIT_A,_T("")); SetDlgItemText(IDC_EDIT_B,_T("")); SetDlgItemText(IDC_EDIT_C,_T("")); } { else GetDlgItemText(IDC_EDIT_B,strTemp); fb = _wtof(strtemp); GetDlgItemText(IDC_EDIT_C,strTemp); fc = _wtof(strtemp); int ndet = m_calcroot.determinant(fa,fb,fc, &fdet); strtemp.format(_t("%g"),fdet); switch (ndet) { case 0:
void CExercise11_1Dlg::OnClickedButtonCalcRoot() SetDlgItemText(IDC_EDIT_RESULT,_T(" 근이없다 ")); SetDlgItemText(IDC_EDIT_DETERMINANT,strTemp); SetDlgItemText(IDC_EDIT_ROOT1,_T("")); SetDlgItemText(IDC_EDIT_ROOT2,_T("")); break; case 1: SetDlgItemText(IDC_EDIT_RESULT,_T(" 중근 ")); SetDlgItemText(IDC_EDIT_DETERMINANT,strTemp); strtemp.format(_t("%g"),m_calcroot.calcroot1(fa,fb,fc)); SetDlgItemText(IDC_EDIT_ROOT1,strTemp); strtemp.format(_t("%g"),m_calcroot.calcroot2(fa,fb,fc)); SetDlgItemText(IDC_EDIT_ROOT2,strTemp); break; case 2: SetDlgItemText(IDC_EDIT_RESULT,_T("2개의근이존재 ")); SetDlgItemText(IDC_EDIT_DETERMINANT,strTemp); strtemp.format(_t("%g"),m_calcroot.calcroot1(fa,fb,fc)); SetDlgItemText(IDC_EDIT_ROOT1,strTemp); strtemp.format(_t("%g"),m_calcroot.calcroot2(fa,fb,fc)); SetDlgItemText(IDC_EDIT_ROOT2,strTemp); break; } }
void CExercise11_1Dlg::OnClickedButtonClear() SetDlgItemText(IDC_EDIT_A,_T("")); SetDlgItemText(IDC_EDIT_B,_T("")); SetDlgItemText(IDC_EDIT_C,_T("")); SetDlgItemText(IDC_EDIT_RESULT,_T("")); SetDlgItemText(IDC_EDIT_DETERMINANT,_T("")); SetDlgItemText(IDC_EDIT_ROOT1,_T("")); SetDlgItemText(IDC_EDIT_ROOT2,_T(""));}