DLL(Dynamic Link Library)

13499 단어
동적 링크 라이브러리와 정적 링크 라이브러리:
동적 링크 라이브러리는 일반적으로 직접 실행할 수 없을 뿐만 아니라, 메시지도 받지 않는다.
애플리케이션과 다른 DLL에서 특정 작업을 수행하도록 호출할 수 있는 여러 함수를 포함하는 독립 실행형 파일입니다.
동적 링크 라이브러리는 다른 모듈이 포함하는 함수를 호출할 때만 시작됩니다.
 
'정적 링크' 는 일반적으로 프로그램 개발 과정에서 발생하는 것으로, 일부 파일을 연결해서 Windows 실행 가능한 파일을 만드는 데 사용된다.
이 파일들은 각양각색의 대상 모듈(OBJ), 실행 라이브러리 파일(.LIB), 통상적으로 컴파일된 자원 파일(.RES)을 포함한다.
반대로 동적 링크는 프로그램이 실행될 때 발생한다. 
정적 라이브러리: 함수와 데이터는 이진 파일로 컴파일되며 확장자는 (.lib) 이다.
정적 라이브러리를 사용하는 경우 링크 실행 파일을 컴파일할 때 다음을 수행합니다.
링크는 정적 라이브러리에서 이 함수와 데이터를 복사하고 프로그램의 다른 모듈과 조합해서 최종 실행 가능한 파일 (.exe) 을 만듭니다.
제품을 발표할 때, 이 실행 가능한 파일만 발표하고, 사용되는 정적 라이브러리는 발표하지 않아도 된다.
 
'동적 링크' 는 윈도우의 링크 과정을 가리키며, 이 과정에서 모듈의 함수를 라이브러리 모듈의 실제 함수와 연결시킨다.
동적 라이브러리: 동적 라이브러리를 사용할 때 가져오는 라이브러리 (.lib, 비필요) 와 (.dll) 파일 두 개를 제공합니다.
가져오기 라이브러리와 정적 라이브러리의 본질적인 차이점:
정적 라이브러리 자체에는 실제 실행 코드와 주소 기호표 등의 데이터가 포함되어 있다.
가져오기 라이브러리의 경우 실제 실행 코드는 동적 라이브러리에 위치하고 가져오기 라이브러리는 주소 기호표 등만 포함하여 프로그램이 대응하는 함수에 대한 기본 주소 정보를 찾을 수 있도록 한다.
동적 링크 라이브러리의 표준 확장자는 (.dll)입니다.Windows 운영 체제에서는 확장자가 (.dll)인 동적 링크 라이브러리만 자동으로 로드할 수 있습니다.
만약 이 파일에 다른 확장자가 있다면, 프로그램은 반드시 명확하게 LoadLibrary () 또는 LoadLibrary Ex () 로 해당 모듈을 불러와야 한다.
 
동적 링크 라이브러리 작성
우리가 작성한 프로그램은 UNICODE 식별자의 정의에 따라 UNICODE 또는 비 UNICODE 문자열을 처리할 수 있는 프로그램으로 컴파일할 수 있습니다.
DLL을 만들 때 문자나 문자열 인자가 있는 함수에는 UNICODE와 비 UNICODE 두 버전이 포함되어야 합니다.
VC++6.0 컴파일러에서 다음을 수행합니다.
File->New->Win32 Dynamic-Link Library->An empty DLL project || An Simple DLL project
An empty DLL 프로젝트와 An Simple DLL 프로젝트의 차이점은 다음과 같습니다. 후자는 간단한 예시 코드가 있습니다.
내 이전의 예를 들면:
새 두 파일: MyDLLh,MyDLL.cpp.
// MyDLL.h
#define
Import extern "C" _declspec(dllexport) Import int sum(int a, int b); Import int sub(int a, int b);

...................................................................................................................................................................................................................................................................
// MyDLL.cpp
#include"MyDLL.h" Import int sum(int a, int b) { return a+b; } Import int sub(int a, int b) { return a-b; }

MyDLL을 마지막으로 컴파일합니다.cpp, 성공하면 Debug에서 MyDLL을 볼 수 있습니다.dll.
팁:
함수 선언 전에 "declspec(dllexport)"을 더하면 함수가 동적 링크 라이브러리로 출력되므로 반드시 입력해야 합니다.
같은 호출 약정 아래 서로 다른 컴파일러를 사용하면 함수 이름에 대한 수식이 다르다.
예를 들어: C 언어와 C++ 언어가 내보낸 dll 파일에서 함수의 수식명은 다르다.
C 언어 스타일의 (.dll) 파일을 원한다면, "extern C"를 붙여서 수식하거나 원본 파일 이름의 접미사를 (.c) 로 변경해야 합니다.
C++ 스타일의 (.dll) 파일을 원한다면 원본 파일 이름 접미사는 (.cpp) 이어야 합니다.
 
호출 방법:
암시적 호출:
MyDLLlib 및 MyDLLh는 이 DLL을 적용해야 하는 프로젝트의 디렉터리에 복사하여 MyDLL을dll을 생성된 프로그램의 디렉터리로 복사합니다.
DLL의 함수를 적용해야 하는 CPP 파일의 시작 부분에 다음과 같은 행이 추가됩니다.
#include"MyDLL.h"
#pragma comment(lib,"MyDLL")

예를 들면 다음과 같습니다.
// MyDLL.cpp
#include #include"MyDLL.h" #pragma comment(lib,"MyDLL") int main(void) { printf("3+6=%d
",sum(3,6)); printf("8-6=%d
",sub(8,6)); return 0; }

 
명시적 호출:
1. MyDLL.lib 및 MyDLLh는 이 DLL을 적용해야 하는 프로젝트의 디렉터리에 복사하여 MyDLL을dll을 생성된 프로그램의 디렉터리로 복사합니다.
CPP 파일을 추가하기 전에 프로젝트->Setting->Link->Object/library modules 상자에 MyDll을 추가해야 합니다.lib 이 라이브러리
마지막으로 생성된 CPP 파일의 시작 부분에 이 행을 추가합니다.
#include"MyDLL.h"

이제 DLL 파일을 사용할 수 있습니다.
2. MyDLL을lib 및 MyDLLh는 이 DLL을 적용해야 하는 프로젝트의 디렉터리에 복사하여 MyDLL을dll을 생성된 프로그램의 디렉터리로 복사합니다.
DLL 파일을 간단하게 호출하는 CPP 파일은 다음과 같습니다.
// MyDLL.cpp
#include #include int main(void) { HMODULE hModule; typedef int (*pSum)(int a, int b); typedef int (*pSub)(int a, int b); pSum Sum = NULL; pSub Sub = NULL; hModule = LoadLibrary("MyDLL.dll"); Sum = (pSum)GetProcAddress(hModule,"sum"); Sub = (pSum)GetProcAddress(hModule,"sub"); printf("3+6=%d
",Sum(3,6)); printf("8-6=%d
",Sub(8,6)); return 0; }

두 가지 함수를 소개합니다.
LoadLibrary() 소개:
기능: 호출 프로세스의 주소 공간에 지정한 모듈을 불러옵니다.지정한 모듈은 다른 모듈을 불러올 수 있습니다.
함수 프로토타입: HMODULE WINAPI LoadLibrary(
LPCTSTR lpFileName//동적 링크 라이브러리의 이름입니다.
                  );
반환값: 함수가 성공하면 반환값은 모듈의 핸들입니다.함수가 실패하면 값이 NULL로 반환됩니다.
 
GetProcAddress() 설명:
기능: 지정된 DLL(Dynamic Link Library)에서 내보낸 함수 또는 변수의 주소를 가져옵니다.
함수 원형: FARPROC WINAPI GetProcAddress(
HMODULE hModule,//모듈의 핸들
LPCSTR lpProcName//함수 또는 변수의 이름 또는 함수의 일련 번호 값입니다.
                  );
반환 값: 함수가 성공하면 반환 값은 함수나 변수를 내보내는 주소입니다.함수가 실패하면 값이 NULL로 반환됩니다.
 
이 코드를 다시 한 번 보십시오: typedef int (*pSum) (int a, int b);
우리가 흔히 볼 수 있는 것은 typedef unsigned Long uLong이다.
사실 typedef int(*pSum)(int a, int b);뜻도 이해하기 쉽다.
pSum 함수 포인터라는 별명을 정의하고, 반환값이 int형이고 두 개의 int형 인자가 포함된 함수 포인터를 가리킨다.
VS2017:
사실 VS2017의 단계는 위와 마찬가지로 모듈 정의 파일에서 DLL 파일을 만드는 방법에 대해 설명합니다.
파일 -> 신규 -> 프로젝트 -> DLL
// MyDLL.cpp
#include "stdafx.h" int sum(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; }

솔루션 -> 리소스 파일 -> 추가 -> 신규 항목 -> 코드 -> 모듈 정의 파일
// Source.def
LIBRARY EXPORTS sum sub

프로젝트 ->MyDLL 속성 -> 링크 -> 입력 -> 모듈 정의 파일:Source.def
마지막: 생성 ->MyDLL
 
암시적 호출과 명시적 호출의 대비:
1. 스텔스 링크 방식은 간단합니다. 처음부터 dll를 불러오고 호출이 필요할 때 직접 호출하면 됩니다.
그러나 프로그램이 여러 DLL 파일에 액세스하는 경우 모두 암시적 링크로 로드할 경우 프로그램이 시작될 때 다음을 수행합니다.
이 dll들은 모두 메모리에 불러오고 호출 프로세스의 주소 공간에 비추어야 프로그램의 시작 시간을 늘릴 수 있습니다.
그리고 일반적으로 프로그램이 실행되는 과정에서 특정한 조건이 충족된 상황에서만 특정한 dll의 함수에 접근해야 한다.
이렇게 하면 모든 dll가 메모리에 불러오면 자원 낭비가 비교적 심각하다.
2. 디스플레이 로딩 방법은 상술한 문제를 해결할 수 있으며 DLL은 필요할 때만 메모리에 로딩된다.
또한 DLL에 스텔스 링크로 액세스할 경우 프로그램이 시작될 때도 LoadLibrary()를 호출하여 프로세스에 필요한 동적 링크 라이브러리를 로드합니다.
 
API 함수가 있는 동적 링크 라이브러리:
DllMain() 엔트리 함수만 있으면 동일한 방식으로 생성됩니다.
// Dll.h 
/*
#define Import extern "C" _declspec(dllexport)
Import void Text(void);
*/
#include"Dll.h"
#include
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpRserved)
{
   switch(ul_reason_for_call)
    {
     case DLL_PROCESS_ATTACH:
          Text();
          break;
     case DLL_PROCESS_DETACH:
          break;
     case DLL_THREAD_ATTACH:
          break;
     case DLL_THREAD_DETACH:
          break;
    }
   return 0;
}
Import void Text(void)
{
   MessageBox (NULL, TEXT ("Hello, World!"), TEXT ("HelloMsg"), MB_OKCANCEL);
}

 
DllMain() 소개:
기능: DLL(Dynamic Link Library)의 선택적 엔트리 포인트
함수 원형: BOOL APIENTRY DllMain(HMODULE hModule,//DLL 모듈의 핸들입니다. DWORD ul reason for call,//DLL 입구점 함수를 호출하는 이유를 나타내는 원인 코드입니다.LPVOID lpvReserved//예약값, 대개 NULL입니다.                  );
매개변수:ulreason_for_call

속뜻
DLL_PROCESS_ATTACH
dll 파일이 프로세스에 처음 로드되었을 때 이 값의 DLL 함수를 호출합니다.
DLL_PROCESS_DETACH
dll 파일이 세션에서 해제되면 이 값의 DLL 함수를 호출합니다.TerminateProcess()는 제외됩니다.
DLL_THREAD_ATTACH
프로세스가 스레드를 만들면 새 스레드가 이 값의 DLL 함수를 호출합니다.
DLL_THREAD_DETACH
ExitThread() 스레드 호출이 끝나면 프로세스에서 이 값 아래의 DLL 함수를 호출합니다.TerminateThread()는 제외됩니다.
반환 값: 시스템에서 DLL 을 사용하는 경우PROCESS_ATTACH 값이 DllMain 함수를 호출하는 경우
호출이 성공하면 TRUE를 반환하고 그렇지 않으면 FALSE를 반환합니다.
 
MFC의 동적 링크 라이브러리 생성과 인용에 관해서는 나중에 다시 이야기합시다!

좋은 웹페이지 즐겨찾기