본문 바로가기
Delphi Tip/파일

DLL(Dynamic-link library)란 (3)

by MonoSoft 2023. 6. 23.
728x90
반응형

DLL(Dynamic-link library)란 (3)

728x90

 

윈도우즈가 실행파일을 구동시키는 과정을 살펴보자.

 

이것은 Windows 95나 Windows NT등의 WIN32에 국한되는 설명이다.

*.EXE

형태의 프로그램이 로딩된다면 우선 커널 프로세스 하나가 생성되어 작동한다.

 

커널 프로세서의 주 역할은 메모리 영역을 구성하는 것이다.

커널 프로세스가 억세스할 수 있는 메모리 범위 는 32bit 범위, 즉 4기가 바이트에 이른다.

 

다음으로 커널파일매핑 프로세스가 생성되어 작동한다.

이 프로세스는 실행파일을 하드디스크등의 저장소로부터 커널 프로세스의

메모리 영역으로 복사한다.

 

이 과정을 통해 실행파일은 실제의 어드레스로 매핑된다.

다음으로 프로그램이 DLL을 이용하고 있다면 이 DLL을 찾아 시스템을 뒤진다.

보통은 현재 디렉토리나 \System 디렉토리를 찾는다.

DLL을 찾는 과정은 뒤에 설명되어 있다.

DLL을 찾았다면 그것이 메모리에 적재되어 있는가를 살핀다.

메모리에 없다면 메모리에 적재한다. 있다면 메모리의 적재과정은 생략된다.

 

이제 DLL의 procedure나 function중 EXE 프로그램에서

사용하는 것의 주소만 커 널 프로세스의 메모리 영역에 매핑시킨다.

EXE 프로그램내의 코드가 DLL 내부의

procedure나 function을 호출할 수 있도록 준비하는 과정이다.

 

이제 프로그램이 실행되면 커널파일매핑 프로세서와

커널 프로세서는 프로그램이 종료될 때까지 유지된다.

프로그램의 종료와 함께 커널파일매핑 프로세스는

매핑 되었던 메모리들의 매핑을 해제한다.

다음으로 커널 프로세스가 모든 메모리를 운영체제로 돌리고 중단된다.

 

[주] 위의 설명에서, RAM이라고 하지 않고 메모리라고

한 이유는 Windows 커널 특성상 메모리를 파일로 페이징하기 때문이다.

 

하드디스크등의 가상메모리를 이 용하기 때문에 Windows의

메모리는 일반적으로 우리가 사용하는

개념의 RAM이라 고만 표현하기에는 무리가 있다.

 

 

 

 

이제, 델파이에서 DLL을 이용하는 방법을 알아보자. 

 

DLL을 이용하기 위해서는 앞 서 살펴본 바와 같이 DLL이

어플리케이션의 커널 프로세스에 매핑되어야 한다.

 

이것을 위해 API 함수 중 LoadLibrary나 LoadLibraryEx를 호출하면 된다.

 

LoadLibrary는 16bit부터 있어온 API이고 32bit에서도

그 구성이 그다지 변하지 않았다.

LoadLibraryEx는 32bit 전용으로 LoadLibrary의 확장판이라고 보면된다.

 

DLL의 매핑이 LoadLibrary를 통해 이루어지지만

DLL을 사용하기 위해 LoadLibrary를 반드시 직접 호출해야 하는 것은 아니다.

 

델파이는 직접(explict) 링크와 간접(implict)링크를 지원한다.

간접(implict)링크를 이용하는 경우 델파이가 LoadLibrary와 FreeLibrary를 자동으로 호출한다.

explict와 implict에 대 해서는 뒤에서 상세히 다루겠다.

 

LoadLibrary와 FreeLibrary는 Windows API 함수로 그것이 선언되어 있는

위치는 \Source\RTL\WIN\Windows.pas 유닛이다. LoadLibrary의 API 선언 원형은 아래와 같다.

 

HINSTANCE LoadLibrary(LPCTSTR lpLibFileName // address of filename of executable module );

 

델파이의 windows.pas내에서 선언된 함수는 다음과 같다.

 

function LoadLibrary( LibFileName: PChar) : HMODULE; stdcall;

 

PChar형으로 주어지는 인자에는 라이브러리 파일명을 주면된다.

 

확장자 .DLL은 생략할 수 있다.

 

또한 파일명으로 완전한 경로명을 줄 수도 있고 단지 파일명만 을 줄 수도 있다.

경로명이 주어지지 않는 경우 델파이는 다음과 같은 순서로 DLL을 찾는다.

 

1. 어플리케이션이 실행된 디렉토리

2. 현재 디렉토리

3. \SYSTEM 디렉토리

4. 디렉토리

5. PATH 환경변수에 지정된 모든 디렉토리 위의 5단계의 검색과정에서도 DLL 파일을 찾을 수 없다면,

LoadLibrary 함수는 0 을 리턴한다. GetLastError를 통해 에러코드를 받을 수 있다.

 

API 함수 LoadLibraryEx 역시 LoadLibrary와 비슷한 구조로 동작하지만

몇가지 기능이 추가되어 있다.

 

LoadLibrary의 확장판이다. Windows.pas에 아래와 같이 선언되어 있다.

 

function LoadLibraryEx(LibFileName: Pchar; hFile:THandle);

 

LoadLibrary나 LoadLibraryEx를 이용하면 DLL을 동적으로

실행 도중에 연결했다가 해제하는 것이 가능하다.

 

즉, DLL을 메모리에 적재하고 진입점(Entry Point) 을 바인딩하는

과정을 필요에 따라 동적으로 처리하는 것이 가능하다는 말이다.

 

 

메모리를 동적으로 연결하는 함수를 간단히 작성해보자.

 

단지 인자가 없는 procedure만 처리할 수 있는 형태지만

이해를 위한 것이로는 충분하다.

 

CallDLLProcedure란 이름의

이 함수는 DLL명과 procedure명을 인자로 받아 DLL을 로딩하고

procedure를 호출하고 복귀전에는 DLL과의 바인딩을 해제한다.

 

 

function CallDLLProcedure ( DLLName, ProcName : String) : Boolean;

type

TDLLProc = procedure;

var

  AProcedure : TDLLProc;

  DLLHandle : THandle;

  ProcPtr : TFarProc;

  MessageStr : String;

begin

  Result := False;

 

  DLLHandle := LoadLibrary(PChar( DLLName ));

 

  if (DLLHandle > 32) then

  begin

    ProcPtr := GetProcAddress( DLLHandle, PChar( ProcName ) );

    @AProcedure := ProcPtr;

 

    if (@AProcedure <> nil ) then

    begin

      AProcedure;

      Result := True;

    end

    else

    begin

      MessageStr := DLLName + ':' + ProcName + '을 찾을 수 없습니다';

      ShowMessage( MessageStr );

    end;

   

    FreeLibrary( DLLHandle ); end

  else

  begin

    MessageStr := DLLName + '을 찾을 수 없습니다';

    ShowMessage( MessageStr );

  end;

end;

 

CallDLLProcedure( 'Sample.DLL', 'HelloWorld' )등과 같이 이용하여

DLL의 특정 procedure를 호출할 수 있다.

 

위예는 인자가 없는 procedure에 국한되지만,

필요에 따라 위의 코드를 참고로 자신의 것을 만들어 사용하면 된다.

 

 

4편계속.....

728x90
반응형

댓글