DLL호출 규칙에 대하여 먼저 언급하고자 한다.
Delphi는 다른 랭귀지에서 사용된 함수들을 쉽게 호출 할 수 있도록 여러 가지 호출 규칙을 가진다.
아래와 같이 5가지 방법이 있다.
- Register(__fastcall) : 레지스터에 등록하여 호출하는 방식
- stdcall(__stdcall) : 가장 일반적으로 활용하는 방식으로 윈도우 표준
- cdecl(__cdecl) : 가변인자가 있는 경우
- pascal(__pascal) : Delphi 최적화 코드를 생성하고자 할 때 스택으로 인자를 저장하는 방식보다는 레지스터를 경유하여 속도 향상
- safecall : OLE 방식에서 이용
※pascal 경우 속도 향상이 된다고 책에는 나와있으나 실제 테스트는 하지 않음.
본 글에서는 stdcall,cdecl,pascal 3가지에 대해서만 샘플을 제공하여 드리겠습니다.
아래 소스를 콜타입들을 바꿔가면서 DLL과 App에서 서로 테스트 해보기시기 바랍니다.
그런데 이상하게도 테스트 하면서 stdcall과 pascal은 서로 상호 호환이 완벽하게 이루어졌습니다. 이 해당 소스만이 그런건지 정확히는 현재 알 수 없습니다.
지금까지 저는 DLL을 안 쓰다가 이번에 새로운 일이 생겼는데 DLL을 호출해서 사용해야 할 일이 생겨서 이것 저것 테스트 하다가 이런 문서도 만들게 되었습니다.
(기존 Delphi만 이용시에는 dcu파일로 배포등을 하여 DLL의 필요성을 알지 못했습니다. ^^;;)
정확한 개념이 잡힌 소스인지… 저도 장담을 못하지만 여러가지로 도움이 되었으면 좋겠습니다.
또한 DLL 생성 및 Delphi 기초에 대하여서는 기타 유용한 사이트 및 책을 이용하시기 바랍니다.
아래 방법으로 공부하시기 바랍니다.(저도 이걸로 공부 중)
- UPCallTypeDLLTest.dll 을 만든다
- UPCallTypeDLLTestApp.exe에서 상기 DLL을 호출한다.
- DLL과 APP를 서로 콜방식을 변경하여 가면서 오류 사항 및 반영내용을 스스로 공부한다.
아래 소스는 Delphi 2010으로 만들었습니다.(Delphi 7로 하려다가 그냥~)
Import 해 올 DLL 파일을 반드시 아래 경로에 존재 하여야 한다.
- [%SystemRoot%] (Windows 디렉토리)
- [%SystemRoot%]\system32\ 경로 (Microsoft Windows XP 일 경우)
- 실행파일(현재 작업) 디렉토리에 같이 위치
- 환경변수 PATH 상의 경로(비추천)
- UPCallTypeDLLTest.dll
1: library UPCallTypeDLLTest;
2:3: uses
4: SysUtils,5: Classes,6: Dialogs;7:8: {$R *.res}9:10: function DLLCallTypePascal(AStr : string) : PChar; pascal;11: var
12: S : string;
13: begin
14: S := AStr;15: S := 'DLL 함수 테스트 : ' + S + ' - pascal';16: ShowMessage(S);17: Result := PChar(S);18: end;
19:20: function DLLCallTypeCdecl(AStr : string) : PChar; cdecl;21: var
22: S : string;
23: begin
24: S := AStr;25: S := 'DLL 함수 테스트 : ' + S + ' - cdecl';26: ShowMessage(S);27: Result := PChar(S);28: end;
29:30: function DLLCallTypeStdcall(AStr : string) : PChar; stdcall;31: var
32: S : string;
33: begin
34: S := AStr;35: S := 'DLL 함수 테스트 : ' + S + ' - stdcall';
36: ShowMessage(S);37: Result := PChar(S);38: end;
39:40: exports
41: DLLCallTypePascal42: ,DLLCallTypeCdecl43: ,DLLCallTypeStdcall44: ;45:46: begin
47: end.
다음은 정적(Static) DLL로 구현 되어져 있다.
- 정적(Static) DLL 이란? 본래의 DLL이라기 보다는 코드의 큰 함수들을 따로 모듈별로 분리 했다가 실행 시 함께 처리한다.
- 동적(Dynamic) DLL(런타임 로딩) 이란 ? DLL은 GetProcAddress라는 API를 사용하여 필요에 따라 첨가하고 필요에 따라 해제시킬 수 있다.
- UPCallTypeDLLTestApp.exe
- UB_Main.pas
1: unit UB_Main;
2:3: interface
4:5: uses
6: Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,7: Dialogs, StdCtrls;8:9: type
10: TfrmUBMain = class(TForm)11: btnPascal: TButton;12: edtPascal: TEdit;13: btnCdecl: TButton;14: edtCdecl: TEdit;15: btnStdcall: TButton;16: edtStdcall: TEdit;17: procedure btnPascalClick(Sender: TObject);
18: procedure btnCdeclClick(Sender: TObject);
19: procedure btnStdcallClick(Sender: TObject);
20: private21: { Private declarations }22: public23: { Public declarations }24: end;
25:26: var
27: frmUBMain: TfrmUBMain;28:29: const
30: ImportDLLFile = 'UPCallTypeDLLTest.dll';31: Msg = '안녕! 세계 (Hellow World!)'; // Hellow World! 국산화 버전 ㅎㅎ
32:33: function DLLCallTypePascal(AStr : string) : PChar; pascal; external ImportDLLFile;34: function DLLCallTypeCdecl(AStr : string) : PChar; cdecl; external ImportDLLFile;35: function DLLCallTypeStdcall(AStr : string) : PChar; stdcall; external ImportDLLFile;36: function DLLCallTypeStdcallNickName(AStr : string) : PChar; stdcall; external ImportDLLFile name 'DLLCallTypeStdcall';37:38: implementation
39:40: {$R *.dfm}41:42: procedure TfrmUBMain.btnCdeclClick(Sender: TObject);
43: var
44: S : PChar;45: begin
46: S := DLLCallTypeCdecl(Msg);47: edtCdecl.Text := S;48: end;
49:50: procedure TfrmUBMain.btnPascalClick(Sender: TObject);
51: var
52: S : PChar;53: begin
54: S := DLLCallTypePascal(Msg);55: edtPascal.Text := S;56: end;
57:58: procedure TfrmUBMain.btnStdcallClick(Sender: TObject);
59: var
60: S : PChar;61: begin
62: S := DLLCallTypeStdcall(Msg);63: edtStdcall.Text := S;64: end;
65:66: end.
PS) 본 소스를 바탕으로 .NET C#과 Visual Basic에서 호출하여 사용하는 방법을 추후 올리겠습니다.
(대부분 C++에서 DLL을 만드는데 전 C++이 약한 관계로 ^^;;)
UPCallTypeDLLTestForDelphi2010.7z
UPCallTypeDLLTestAppForDelphi2010.7z
UPCallTypeDLLTestGroupForDelphi2010(All).7z
'Language > Delphi(VCL,Pascal)' 카테고리의 다른 글
[Delphi] Form Style - fsStayOnTop 대체 방법 (0) | 2011.07.27 |
---|---|
[Delphi] Form Style이 fsStayOnTop 일 경우 다이얼로그(Dialog) 박스가 뒤로 숨는 문제 (0) | 2011.07.27 |
[Delphi] Form Style이 fsStayOnTop일 경우 메세지 박스가 뒤로 숨는 문제 (0) | 2011.07.27 |
[Delphi] Form Style이 fsStayOnTop일 경우 메세지 박스가 뒤로 숨는 문제 (0) | 2011.07.27 |
[Delphi] 동적 DLL 호출 방법 (0) | 2010.04.28 |