Delphi의 DLL 지식 학습 5 - Delphi 응용 프로그램에서 DLL 사용

5652 단어 Delphi
DLL을 호출하는 방법에는 암시적 및 명시적 두 가지가 있습니다.방금 생성한 DLL의 경우 두 가지 방법을 살펴보겠습니다.
은식
이 장에서 만든 첫 번째 D L L에는 인터페이스 장치가 포함되어 있습니다.다음은 DLL을 암시적으로 연결하는 인터페이스 유닛입니다.이 프로젝트의 메인 창에는 TMadk Edit 하나, TButton 하나, Tlabel 9개가 있습니다.
이 프로그램에서 사용자는 미분의 수를 입력한 다음 단추를 누르면 탭에 항목별로 결과를 표시합니다.이 결과는 PenniesLib에서 나온 것입니다.dll에서 가져온 루틴 Pennies ToCoins().
메인 창은MainFrm입니다.pas 단원에 정의된 코드
unit MainRrm;



interface

uses

    SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,

    Forms, Dialogs, StdCtrls, Mask;

type

    TMainForm = class(TForm)

        lblTotal: TLabel;

        lblQlbl: TLabel;

        lblDlbl: TLabel;

        lblNlbl: TLabel;

        lblPlbl: TLabel;

        lblQuarters: TLabel;

        lblDimes: TLabel;

        lblNickels: TLabel;

        lblPennies: TLabel;

        btnMakeChange: TButton;

        meTotalPennies: TMaskEdit;

        procedure btnMakeChangeClikc(sender: TObject);

    end;



var MainForm: TMainForm;



implementation

uses PenniesInt;

{R *.DFM}



procedure TMainForm.btnMakeChangeClick(Sender: TObject);

var

    CoinsRec: TCoinsRec;

    TotPennies: word;

begin

    {call the DLL function to determine the minimum coins required

    for the amount of pennies specified}

    TotPennies:= PenniesToCoins(StrToInt(meTotalPennies.Text), @CoinsRec);

    with CoinsRec do

    begin

        {Now display the coin information}

        lblQuarters.Caption:= IntToStr(Quarters);

        lblDimes.Caption:= IntToStr(Dimes);

        lblNickels.Caption:= IntToStr(Nickels);

        lblPennies.Caption:= IntToStr(Pennies);

    end;

end;



end.


MainFrm에 주의하세요.pas는 인터페이스 장치 PenniesInt를 사용합니다.PenniesInt.pas에는 PenniesLib이 포함됩니다.dpr의 함수에 대한 외부 설명입니다.Win 32 시스템은 응용 프로그램이 실행될 때 자동으로 Pennies Lin으로 이동합니다.dll, 이 프로그램의 프로세스 주소 공간에 비추기
import 인터페이스 단원은 Pennies Int 단원을 사용하지 않고MainFrm에서 선택할 수 있습니다.pas의 implementation 부분은 PenniesToCoins() 함수를 외부에서 설명하면 됩니다. 코드는 다음과 같습니다.
implementation



function PenniesToCoins(TotPennies: word; ChangeRec: PChangeRec): Word; stdcall; external 'PENNIESLIB.DLL';


하지만 MainFrm에서.pas는 PChangeRec와 TchangeRec를 다시 정의해야 합니다. 그렇지 않으면 컴파일 명령인 PENIESLIB를 사용하여 프로그램을 컴파일할 수도 있습니다.이 기술은 DLL의 일부 루틴에 액세스하기만 하면 적절합니다.그러나 대부분의 경우 DLL에 접근해야 할 뿐만 아니라 DLL에 정의된 데이터 형식도 인용해야 하기 때문에 인터페이스 단원을 사용하는 것이 가장 좋다
주의: 어떤 때는 다른 소프트웨어 업체의 DLL을 호출해야 하는데, 이때는Pascal의 인터페이스 단원이 없을 수도 있지만, C/C++의 도입 라이브러리가 있을 수도 있습니다.만약 그렇다면, 이 라이브러리를 같은 효과의 Pascal 인터페이스 단원으로 현시하기만 하면 됩니다.
 
2. 현식 호출
비록 스텔스 호출은 매우 편리하지만, 가장 이상적인 방법은 아니다.만약 여러 개의 루틴을 포함하는 DLL이 있다면, 이 루틴들은 쓸모가 없을 수도 있다. 그러면, 이 DLL로 가져오는 것은 메모리를 낭비하는 것이 분명하다.특히 하나의 애플리케이션에 여러 개의 DLL을 사용해야 하는 경우에는 이러한 비용이 낭비됩니다.또 다른 상황은 여러 버전의 표준 함수인 프린터 드라이버 한 세트가 각각 여러 개의 DLL로 이루어진다는 것이다.이 경우 필요한 버전의 DLL을 호출하는 것이 가장 좋습니다.이런 방식은 바로 호출을 표시하는 것이다.
unit MainFrm;



interface

uses

    SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,

    Forms, Dialogs, StdCtrls;



type

    TShowCalendar = function(AHandle: THandle; ACaption: String): TDateTime; Stdcall;



    EDLLLoadError = class(Exception);



    TMainForm = class(TForm)

        lblDate: TLabel;

        btnGetCalendar: TButton;

        procedure btnGetCalendarClick(Sender: TOnject);

    end;



var

    MainForm: TMainForm;



implementation

{$R *.DFM}



procedure TMainForm.btnGetCalendarClick(Sender: TObject);

var

    LibHandle: THandle;    //!!!!!

    ShowCalendar: TShowCalendar;    //!!!!!!

begin

    LibHandle:= LoadLibrary('CALENDARLIB.DLL');    //!!!!!!

    try

        if LibHandle = 0 then

            raise EDLLLoadError.Create('Unable to load DLL');



        @ShowCalendar:= GetProcAddress(LibHandle, 'ShowCalendar');



        if not(@ShowCalendar = nil) then

            lblData.Caption:= DateToStr(ShowCalendar(Application.Handle, Caption))

        else

            RaiseLastWin32Error;

    finally

        FreeLibrary(LibHandle);

    end;

end;



end.


위의 단원은 먼저 프로세스 데이터 형식인 TShow Calendar를 정의했는데 이 유형은Calendar Lib입니다.dll의 함수 형식입니다.이어 호출이 실패할 때 이 이상을 일으킬 수 있는 특수한 이상류를 성명했다.btnGetCalendarClick () 이벤트 처리 과정에서 세 개의 Win32 API 함수를 사용했습니다: LoadLibrary (), FreeLibrary (), GetProcAddress ().
LoadLibrary() 선언은 다음과 같습니다.
function LoadLibrary(lpLibFileName: PChar): HMODULE; stdcall;


위 함수는 lpLibFileName 매개 변수로 지정된 DLL 모듈로 가져와 호출 프로세스의 주소 공간에 매핑합니다.호출에 성공하면 함수는 이 모듈의 핸들을 되돌려줍니다.실패하면 0 값을 되돌려주고 이상을 일으킵니다.온라인 도움말에서 LoadLibrry () 함수에 대한 상세한 설명과 되돌아올 수 있는 오류 값을 볼 수 있습니다
FreeLibrary() 선언은 다음과 같습니다.
function FreeLibrary(hLibModule: HMODULE): BOOl; stdcall;


FreeLibrary() 함수는 LibModule에서 지정한 라이브러리의 인스턴스 수를 줄입니다.이 DLL의 인스턴스 수가 0일 경우 호출된 DLL이 해제됩니다.인스턴스 수 이 DLL을 사용한 작업 수를 기록합니다.
GetProcAddress()는 이렇게 정의됩니다.
function GetProcAddress(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall;


GetProcAddress () 는 함수가 모듈에 있는 주소를 되돌려줍니다. 이 주소는 hModule 파라미터가 모듈을 지정합니다.hModule은 LoadLibrary() 함수에서 반환된 결과 THandle입니다.GetProcAddress() 호출이 실패하면 nil로 돌아갑니다.자세한 오류 정보는 GetLastError () 를 호출해야만 얻을 수 있습니다.
Button1의 OnClick 이벤트 처리 프로세스에서 먼저 LoadLibrary()를 호출하여 CALDLL을 호출합니다.실패할 경우 예외가 발생합니다.성공하면 GetProcAddress()를 호출하여 함수 ShowCalendar()의 주소를 가져옵니다.변수 ShowCalendar 앞에 주소 지정 연산자@를 추가하면 컴파일할 때 유형 변환 오류가 발생하지 않습니다.함수 Show Calendar () 의 주소를 얻으면 TShow Calendar가 정의한 대로 사용할 수 있습니다.마지막으로 사용하지 않을 때finally 블록에서 FreeLibrary () 를 호출해서 풀어야 합니다.
이 함수를 호출할 때마다 DLL을 불러올 뿐만 아니라 풀어야 한다는 것을 알 수 있을 것이다.만약 응용 프로그램이 실행될 때 한 번만 호출하면 현식 호출의 장점이 뚜렷하고 메모리의 소모를 효과적으로 줄일 수 있다.그러나 이 함수가 빈번하게 호출되려면 빈번하게 호출되고 방출되면 시스템의 부담이 커진다.

좋은 웹페이지 즐겨찾기