Delphi에서 동적 링크 라이브러리 두 가지 호출 방식의 비교

6429 단어 Delphi
1. 동적 링크 라이브러리의 개념
동적 링크 라이브러리(Dynamic Link Library, 줄여서 DLL)는 다른 응용 프로그램에서 공유할 수 있는 프로그램 모듈로 공유할 수 있는 절차와 자원을 봉인한다.동적 링크 라이브러리 파일의 확장자는 일반적으로 dll이며 drv,sys,fon일 수도 있습니다. 이것은 실행 가능한 파일 (exe) 과 매우 유사합니다. DLL에 실행 가능한 코드가 포함되어 있지만 단독으로 실행할 수 없고 Windows 프로그램에서 직접 또는 간접적으로 호출해야 한다는 차이점이 있습니다.
동적 링크는 정적 링크에 대한 것입니다.정적 링크란 호출할 함수나 과정을 실행 가능한 파일에 연결시켜 실행 가능한 파일의 일부분이 되는 것을 말한다.다시 말하면 함수와 과정의 코드는 프로그램의exe 파일에 있으며, 이 파일은 실행할 때 필요한 모든 코드를 포함한다.여러 프로그램이 같은 함수를 호출할 때 메모리에 이 함수의 여러 복사본이 존재하기 때문에 귀중한 메모리 자원을 낭비한다.동적 링크에서 호출된 함수 코드는 응용 프로그램의 실행 가능한 파일로 복사되지 않고 호출된 함수에 대한 설명 정보만 추가되었다(왕왕 위치 변경 정보).응용 프로그램이 메모리에 불러와 실행을 시작할 때만 Windows의 관리 아래 응용 프로그램과 해당하는 DLL 사이의 링크 관계를 맺을 수 있습니다.Windows는 호출된 DLL의 함수를 실행할 때 링크에서 생성된 재배치 정보에 따라 DLL의 함수 코드를 실행합니다.
일반적인 상황에서 만약에 한 응용 프로그램이 동적 링크 라이브러리를 사용한다면 Win32시스템은 메모리에 DLL의 복제품만 있다는 것을 보장한다. 이것은 메모리 맵 파일을 통해 이루어진 것이다.DLL은 먼저 Win32 시스템의 전역 스택으로 이동한 다음 이 DLL을 호출하는 프로세스 주소 공간에 비칩니다.Win32 시스템에서, 모든 프로세스는 자신의 32비트 선형 주소 공간을 가지고 있으며, 만약 하나의 DLL이 여러 프로세스에 호출된다면, 모든 프로세스는 이 DLL의 이미지를 받을 것이다.16비트 Windows와 달리 Win32에서 DLL은 각 프로세스의 코드로 간주됩니다.
2. 동적 링크 라이브러리의 장점
1. 코드, 리소스 및 데이터 공유
DLL을 사용하는 주요 목적은 코드를 공유하기 위해서이며 DLL의 코드는 모든 Windows 응용 프로그램에 공유될 수 있다.
2. 실현된 세부 사항 숨기기
DLL의 루틴은 애플리케이션에서 액세스할 수 있지만 자세한 루틴은 애플리케이션에서 알 수 없습니다.
3. Delphi와 같은 개발 도구의 기능 확대
DLL은 언어와 무관하기 때문에 C++, VB 또는 동적 링크 라이브러리를 지원하는 언어에 호출되는 DLL을 만들 수 있습니다.이렇게 하면 한 언어가 부족하면 다른 언어에서 만든 DLL에 액세스하여 이를 보완할 수 있습니다.
3. 동적 링크 라이브러리의 실현 방법
1. Load-time Dynamic Linking
이런 용법의 전제는 컴파일하기 전에 DLL에서 몇 개의 함수를 호출해야 하는지 명확하게 알고 컴파일할 때 목표 파일에 필요한 링크 정보만 보존하고 DLL 함수의 코드는 포함하지 않는다는 것이다.프로그램이 실행될 때, 링크 정보를 이용하여 DLL 함수 코드를 불러오고 메모리에서 그 체인을 호출 프로그램의 실행 공간에 연결하는데, 그 주요 목적은 코드 공유에 편리하도록 하는 것이다.
2. Run-time Dynamic Linking
이런 방식은 컴파일하기 전에 어떤 DLL 함수를 호출할지 모르고 실행 과정에서 필요에 따라 어떤 함수를 호출해야 할지 결정하고 LoadLibrary와 GetProcAddress로 DLL 함수의 입구 주소를 동적으로 얻는 것을 말한다.
4. DLL의 두 가지 호출 방식이 Delphi에서의 비교
DLL을 작성하는 목적은 다른 프로그램에서 호출할 수 있도록 프로그램을 출력하기 위해서입니다. 따라서 DLL의 프로젝트 파일에서 출력된 프로세스를 Exports 키워드로 끌어내야 합니다.DLL을 호출하는 응용 프로그램에서 사용된 DLL의 방법을 선언해야 합니다. 선언 형식은 DLL의 선언과 동일해야 합니다.DLL에 액세스하는 프로세스에는 정적 호출과 동적 호출 두 가지 방법이 있습니다.정적 호출 방식은 단원의 Interface 부분에서 External 지시자로 DLL에서 도입할 예시를 표시하는 것이다.동적 호출 방식은 Windows를 호출하는 API를 통해 LoadLibrary 함수, GetProcAddress 함수, FreeLibrary 함수를 동적으로 DLL에 도입하는 예이다.
정적 호출 방식에 필요한 코드는 동적 호출 방식에 필요한 것보다 적지만 부족한 부분이 있다. 첫째, 불러올 DLL이 존재하지 않거나 DLL에 도입할 절차가 없으면 프로그램이 자동으로 실행을 중지한다.둘째, DLL이 더 이상 필요하지 않아도, DLL이 불러오면 프로그램의 주소 공간에 머물러 있습니다.동적 호출 방식은 상기 문제를 해결할 수 있습니다. DLL이 필요할 때만 LoadLibrary 함수를 도입하고, 다 사용한 후에 FreeLibrary 함수를 통해 메모리에서 마운트 해제하며, GetProcAddress 함수를 조정하면 서로 다른 절차를 지정할 수 있습니다.무엇보다 지정된 DLL 오류가 발생할 경우 API 호출이 실패할 수 있으므로 프로그램이 종료되지 않습니다.다음은 구체적인 실례를 통해 이 호출 방식의 사용 방법을 설명할 것이다.
1. 정적 호출 방식
예시 프로그램은 두 개의 정수를 구하는 함수만 포함하는 DLL을 만들었고, 메인 프로그램에 두 개의 정수를 입력했다. 이 DLL을 호출하면 두 개의 정수의 합을 구할 수 있다.
이 DLL의 프로그램 코드는 다음과 같습니다.
library AddNum;
uses
SysUtils,
Classes;
{$R *.res}
function AddNumber(Num1,Num2:integer):integer;stdcall; //
 begin
  result:=Num1+Num2;
 end;
  exports
  AddNumber; //
 begin
end.

마스터 프로그램은 DLL을 호출할 때 먼저 호출할 함수를 인터페이스 섹션에 선언합니다.
function AddNum(Num1,Num2:integer):integer;stdcall;external 'AddNum.dll'
name 'AddNumber';

그런 다음 버튼 컨트롤의 이벤트에 다음 코드를 씁니다.
procedure TForm1.Button1Click(Sender: TObject);
var
 Number1,Number2:integer;
 Sum:integer;
begin
 Number1:=strtoint(Edit1.Text);
 Number2:=strtoint(Edit2.Text);
 Sum:=AddNum(Number1,Number2); //
 Edit3.Text:=inttostr(Sum);
end;

2. 동적 호출 방식
이 예시 프로그램은 창을 포함하는 날짜를 표시하는 DLL을 만들었습니다.
프로그램에서 Show Calendar 함수를 정의하여 이 창에 설정된 날짜를 되돌려줍니다.함수 정의는 다음과 같습니다.
function ShowCalendar(AHandle: THandle; ACaption: String): TDateTime;
var
 DLLForm: TDLLForm;
begin
 Application.Handle := AHandle;
 DLLForm := TDLLForm.Create(Application); //
 try
  DLLForm.Caption := ACaption;
  DLLForm.ShowModal; //
  Result := DLLForm.calDLLCalendar.CalendarDate; //
 finally
  DLLForm.Free; //
 end;
end;

DLL의 프로젝트 파일에서 exports Show Calendar를 사용합니다.문장은 이 함수를 끌어낸다.다음은 간단한 애플리케이션을 통해 DLL 파일을 테스트해 보겠습니다.새 프로젝트 파일은 창에 Label 컨트롤과 버튼 컨트롤을 배치하고 버튼 컨트롤의 OnClick 이벤트에 다음 코드를 작성합니다.
procedure TMainForm.Button1Click(Sender: TObject);
var
 OneHandle : THandle; //
begin
 OneHandle := LoadLibrary('Clendar.dll'); // DLL,
 try
  if OneHandle <> 0 then // ShowCalendar
   @ShowCalendar := GetProcAddress(OneHandle, 'ShowCalendar');
   if not (@ShowCalendar = nil) then
    // Label1 DLL
    Label1.Caption := DateToStr(ShowCalendar(Application.Handle, Caption))
   else
    RaiseLastWin32Error;
 finally
  FreeLibrary(OneHandle); // DLL
 end;
end;

위 프로그램에서 DLL의 동적 호출 방식이 정적 호출 방식보다 우수한 점을 볼 수 있다.DLL 루틴은 사용이 끝난 후에야 불러오고, 사용이 끝난 후에 마운트 해제되어 시스템 자원의 점용을 크게 줄였다.LoadLibrary 함수를 호출할 때 DLL의 전체 경로를 명시적으로 지정할 수 있으며, 경로가 지정되지 않은 경우 런타임 시 응용 프로그램이 로드한 디렉토리를 먼저 찾은 다음 Windows 시스템의 System 디렉토리 및 환경 변수Path에서 설정한 경로를 찾을 수 있습니다.
끝말
동적 링크 라이브러리는 코드와 자원의 공유를 실현하고 시스템 자원의 점용을 크게 줄일 수 있기 때문에 현재 응용 프로그램 개발에서 매우 중요한 역할을 한다.Delphi는 현재 유행하는 응용 소프트웨어 개발 도구로 본고는 Delphi에서 동적 링크 라이브러리를 어떻게 사용하는지에 대해 어느 정도 논술했다.

좋은 웹페이지 즐겨찾기