1. 첫 번째 DLL 프로젝트를 시작하십시오
1.file-> 닫기 All-> file-> new [dll >를 닫습니다
코드 : |
// 다음과 같이 코드를 자동으로 생성합니다 도서관 project2; // 이것은 말도 안됩니다. 용도 sysutils, 수업; {$ r *.res} 시작하다 끝. |
2. 입력 할 기능을 추가하십시오.
코드 : |
도서관 project2; 용도 sysutils, 수업; 함수 mymax (x, y : 정수) : 정수; 시작하다 x> y라면 결과 : = x 또 다른 결과 : = y; 끝 ; // 기억 : 라이브러리의 이름은 중요하지 않지만 DLL-Func의 경우는 관련이 있습니다. // dll-func-name에서 mymax를 쓰는 것은 mymax와 다릅니다. 잘못 쓰여진 경우 즉시 // 결과는이 DLL을 사용하는 AP를 전혀 열 수 없다고 요청합니다. // 매개 변수의 상단 및 하부 사례는 괜찮습니다. 같은 이름을 가질 필요조차 없습니다. 프로토 타입이 (X, Y : Integer) 인 경우 // 제 시간에 (a, b : integer)로 씁니다. 괜찮습니다. // 기억하십시오 : 다른 stdcall을 추가하십시오. 이 책은 델파이를 사용하여 DLL을 쓰고 있다면 // Delphi-AP가 BCB/VC-AP 등을 사용하기를 희망하면 stdcall을 추가하는 것이 좋습니다. // 매개 변수 패턴 : Delphi에는 많은 가변 패턴이 있습니다. 물론 DLL이 좋아하는 것은 아닙니다. // Windows/DLL의 모국어는 C 여야합니다. 그래서 우리가 DLL의 매개 변수를 통과시키고 싶다면 우리는 // 규칙에 따라 가능한 한 많이 사용하십시오. 이 두 가지를 쓰면 후자는 많은 문제가 될 것입니다. C에 익숙하지 않은 경우 // 괜찮다면. 나중에 이야기하겠습니다. {$ r *.res} 시작하다 끝. |
3.이 공유 기능을 DLL에서 보내고 외부 세계 (Delphi-AP)를 사용하게하십시오 : Guangru
따라서 AP는 이것을 사용할 수 없으므로 내보내기를 추가해야합니다.
코드 : |
{$ r *.res} 수출 mymax; 시작하다 끝. |
4. 좋아, Ctrl-F9를 눌러 컴파일 할 수 있습니다. 현재 F9를 누르지 마십시오. DLL은 별도로 실행할 수없는 exe ex가 아닙니다. 현재 DLL에 오류가 있으면 수정하십시오. Ctrl-F9를 다시 누릅니다. 현재 경고가있을 수 있습니다. 문제가되지 않습니다. 그냥 연구하고 살펴보십시오. Ctrl-F9를 다시 누른 다음 "완료, 컴파일". 동일한 디렉토리에는 *.dll이 있습니다. 축하합니다. 작업이 완료되었습니다.
2. 테스트 수행 : 새 응용 프로그램 열기 :
1. tbutton을 추가하십시오
코드 : |
showmessage (inttostr (mymax (30,50))); |
2. exe에게 func를 잡기 위해 거기에 가라고 말하십시오.
코드 : |
// 형태, 인터페이스, var에 추가하십시오 MyMax (X, Y : Integer) : 정수; // mytestdll.dll은 이전에 dll 프로젝트 이름을 씁니다. // DLL 이름이 상단 및 하단인지는 중요하지 않습니다. 그러나 확장자를 추가해야합니다 .dll. Win95 또는 NT에서 // 확장자를 추가 할 필요는 없지만이 두 OS는 점점 더 적을 수 있습니다. 확장을 추가해야합니다. |
좋아, 간단하다.
위의 예가 매우 간단합니까? Delphi에 익숙한 친구들은 위의 코드가 기본적으로 일반 델파이 프로그램을 작성하는 것과 동일하다는 것을 알 수 있습니다. TestDLL 기능 후에 추가 stdcall 매개 변수가 있고 TestDll 함수가 내보내기 명령문을 사용하여 선언됩니다. 위의 코드를 컴파일하면 delphi.dll이라는 동적 링크 라이브러리를 얻을 수 있습니다. 이제주의가 필요한 것을 봅시다. 1. DLL로 작성된 모든 기능 또는 절차에는 stdcall 호출 매개 변수와 함께 추가되어야합니다. Delphi 1 또는 Delphi 2 환경에서는 통화 매개 변수가 멀리 있습니다. Delphi 3 후,이 매개 변수는 최적화 된 레지스터 매개 변수 대신 표준 Win32 파라미터 전송 기술을 사용하기 위해 STDCALL로 변경되었습니다. STDCALL 매개 변수를 사용하는 것을 잊어 버린 경우이 오류는 DLL의 컴파일 및 생성에 영향을 미치지 않지만이 DLL을 호출 할 때 심각한 오류가 발생합니다. 그 이유는 레지스터 매개 변수가 델파이의 기본 매개 변수이기 때문입니다.
2. 작성된 기능 및 절차는 수출문을 사용하여 외부 기능으로 선언해야합니다.
보시다시피, testdll 함수는 외부 함수로 선언됩니다. 이를 통해 기능을 외부로 볼 수 있습니다. 특정 방법은 "빠른보기"기능을 사용하여 마우스를 마우스 오른쪽 버튼으로 클릭하여 DLL 파일을 보는 것입니다. (빠른보기 옵션이 없으면 Windows CD에서 설치할 수 있습니다.) TestDll 함수가 내보내기 테이블 바에 나타납니다. 또 다른 좋은 이유는 우리가 이런 식으로 선언하지 않으면 우리가 쓴 기능이 호출되지 않기 때문에 아무도보고 싶어하지 않는 것입니다.
3. 긴 문자열 유형 매개 변수와 변수를 사용하는 경우 Sharemem을 참조해야합니다.
델파이의 문자열 유형은 매우 강력합니다. 우리는 일반 문자열의 길이가 최대 256 자이지만 델파이의 문자열 유형은 기본적으로 2G에 도달 할 수 있습니다. (예, 당신은 그것을 올바르게 읽으십시오. 실제로 두 메가 바이트입니다.) 현재 문자열 유형 매개 변수, 가변 또는 녹음 정보를 사용한다고 주장하면 Sharemem 장치를 참조해야하며 첫 번째 참조 여야합니다. . 사용 명령문 이후 첫 번째 참조 단위입니다. 다음 예에서 볼 수 있듯이 :
용도
Sharemem,
sysutils,
수업;
또 다른 요점은 단위 파일 (*.pas) 대신 프로젝트 파일 (*.dpr)에서 동일한 작업을 수행해야한다는 것입니다. 이 작업을 수행하지 않으면 충돌이 발생할 수 있습니다. 문자열 유형을 사용하지 않는 방법은 문자열 유형의 매개 변수, 변수 등을 pchar 또는 shortstring (예 : s : string [10]) 유형을 선언하는 것입니다. 동적 배열을 사용할 때 동일한 문제가 발생합니다. 솔루션은 위에서 설명한 것과 같습니다.
3 장 : Delphi에서 DLL TOP에 정적 호출
DLL을 부르는 것보다 DLL을 호출하는 것이 더 쉽습니다. 먼저, 정적 호출 방법을 소개하고 나중에 동적 호출 방법을 소개하고 두 가지 방법을 비교할 것입니다. 마찬가지로 먼저 정적 호출의 예를 들어 보겠습니다.
단위 유닛 1;
인터페이스
용도
Windows, 메시지, sysutils, 클래스, 그래픽,
제어, 형태, 대화, stdctrls;
유형
tform1 = 클래스 (tform)
edit1 : 테디;
버튼 1 : tbutton;
절차 버튼 1Click (sender : tobject);
사적인
{개인 선언}
공공의
{공개 선언}
끝;
var
form1 : tform1;
구현
{$ r *.dfm}
//이 줄의 다음 코드는 우리가 실제로 쓴 코드입니다.
함수 testdll (i : 정수) : 정수; stdcall;
외부 'delphi.dll';
절차 tform1.Button1click (sender : tobject);
시작하다
edit1.text : = inttostr (testdll (1));
끝;
끝.
위의 예에서, 우리는 편집 상자 (편집)와 양식의 버튼을 배치하고 방금 쓴 delphi.dll을 테스트 할 코드가 거의 없습니다. 우리가하는 유일한 작업은 TestDLL 기능의 설명을 구현에 넣고 외부 명령문과 함께 delphi.dll의 위치를 지정하는 것임을 알 수 있습니다. (이 예에서는 통화 프로그램과 delphi.dll이 동일한 디렉토리에 있습니다.) 우리가 쓴 testdll 기능이 델파이에 의해 빠르게 인정된다는 것은 흥미 롭습니다. 다음과 같은 실험을 수행 할 수 있습니다. "TestDll ("를 입력하면 곧 Delphi가 플라이 바이 프롬프트 표시 줄을 사용하여 Delphi에 정의 된 다른 기능을 사용하는 것만 큼 간단하게 입력 해야하는 매개 변수를 프롬프트 할 것입니다.
다음:
1. stdcall을 사용하여 매개 변수를 호출하십시오.
위에서 언급했듯이 DLL의 기능 및 절차를 참조 할 때 위에서 언급 한 것과 동일한 이유로 STDCALL 매개 변수도 사용해야합니다.
2. 외부 문을 사용하여 호출 된 dll 파일의 경로와 이름을 지정하십시오.
보시다시피, 우리는 외부 명령문에서 호출 될 dll 파일의 이름을 지정합니다. DLL 파일과이를 불리는 기본 프로그램이 동일한 디렉토리에 있기 때문에 쓰기 경로가 없습니다. dll 파일이 c :/에 있으면 위의 참조 문을 외부 'c : /delphi.dll'으로 쓸 수 있습니다. 파일의 접미사 .dll은 작성해야합니다.
3. DLL에서 글로벌 변수를 호출 할 수 없습니다.
다음과 같은 DLL에서 어떤 종류의 글로벌 변수를 선언하면 : var s : byte. 이러한 방식으로, 글로벌 변수 S는 DLL에서 정상적으로 사용할 수 있지만 통화 프로그램에서는 S를 사용할 수 없으며 S는 통화 프로그램에 전역 변수로 전달 될 수 없습니다. 그러나 호출 프로그램에서 선언 된 변수는 DLL에 매개 변수로 전달 될 수 있습니다.
4. 호출 된 DLL이 존재해야합니다.
이는 중요합니다. 정적 호출 방법이 호출되는 경우 호출되는 기능 또는 절차 등이 있어야합니다. 지정된 경로와 파일 이름이 존재하지 않거나 지정된 경로와 파일 이름이 잘못된 경우, 기본 프로그램을 실행할 때 시스템이 "프로그램을 시작하는 동안 오류가 발생했습니다"또는 "찾기 없음 *.dll 파일"이 프롬프트됩니다.
4 장 Delphi에서 DLL Top을 동적으로 호출합니다
동적으로 DLL을 호출하는 것은 비교적 복잡하지만 매우 유연합니다. 문제를 철저히 설명하기 위해 이번에는 C ++로 작성된 DLL을 호출하는 예를 제시합니다. 먼저 C ++에서 다음 DLL 소스 프로그램을 컴파일하십시오.
#포함하다
extern "c"_declspec (dllexport)
int winapi testc (int i)
{
반환 i;
}
컴파일 후 DLL 파일이 생성됩니다. 편의를 위해, 우리는 여전히 위의 호출 프로그램을 참조하지만 Button1click 프로세스의 원본 문을 다음 코드로 바꿉니다.
절차 tform1.Button1click (sender : tobject);
유형
tintfunc = function (i : 정수) : 정수; stdcall;
var
Th : thandle;
TF : Tintfunc;
TP : TFARPROC;
시작하다
Th : = loadLibrary ( 'cpp.dll');
그렇다면
노력하다
tp : = getProcadDress (th, pchar ( 'testc'));
tp <> nil 인 경우
그런 다음 시작하십시오
tf : = tintfunc (tp);
edit1.text : = inttostr (tf (1));
끝
또 다른
showmessage ( 'testc 함수를 찾을 수 없음');
마지막으로
Freelibrary (Th);
끝
또 다른
showmessage ( 'cpp.dll found');
끝;
보시다시피,이 동적 통화 기술은 매우 복잡하지만 loadlibrary ( 'cpp.dll')에서 'delphi.dll'으로 DLL 이름을 수정하는 등 매개 변수를 수정하는 한 DLL이라고합니다.
1. 호출 할 함수 또는 절차의 유형을 정의하십시오.
위의 코드에서 우리는 전화 할 기능 testc에 해당하는 tintfunc 유형을 정의합니다. 동일한 정의 작업은 다른 통화에서 수행되어야합니다. 또한 stdcall 호출 매개 변수를 추가하십시오.
2. 호출 된 DLL을 릴리스하십시오.
우리는 dll을 loadlibrary와 동적으로 호출했지만 사용 후 Freelibrary로 DLL을 수동으로 해제해야한다는 것을 기억하십시오. 그렇지 않으면 Windows를 종료하거나 종료 될 때까지 DLL이 메모리를 차지합니다.
이제 DLL을 호출하는 두 가지 방법의 장점과 단점을 평가해 봅시다. 정적 방법은 구현하기 쉽고 마스터하기 쉽고 일반적으로 약간 빠르며 더 안전하고 신뢰할 수 있지만 정적 방법은 런타임에 필요한 DLL을 유연하게로드하고 내릴 수 없지만 주 프로그램이 시작될 때 지정된 DLL을로드합니다. DLL이 프로그램 끝에서만 출시 될 때까지 실행되며 Delphi와 같은 컴파일러 기반 시스템만이 방법을 사용할 수 있습니다. 동적 방법은 정적 방법에서 단점을 더 잘 해결하고 DLL에서 기능 및 절차에 쉽게 액세스 할 수 있으며, 일부 기존 버전의 DLL에서는 동적 방법이 완전히 마스터하기가 어렵습니다 기능 또는 절차는 많은 복잡한 유형과 호출 방법을 정의해야합니다. 초보자의 경우 저자는 정적 메소드를 사용한 다음 능숙한 후 동적 통화 방법을 사용하는 것이 좋습니다.
5 장 DLL 상단 사용을위한 실용적인 팁
1. 작문 기술.
1. DLL의 정확성을 보장하기 위해 먼저 일반 응용 프로그램의 일부로 작성하여 올바르게 디버깅 한 다음 주 프로그램에서 분리하여 DLL으로 컴파일 할 수 있습니다.
2. DLL의 보편성을 보장하기 위해 DLL에 시각적 제어 이름이 나타나지 않도록해야합니다 일부 기록.
3. 디버깅을 용이하게하기 위해서는 각 기능과 프로세스는 가능한 한 짧고 간결해야하며 구체적이고 상세한 주석이 동반되어야합니다.
4. Try-Finally는 가능한 오류와 예외를 처리해야합니다.
5. DLL의 크기를 줄이기 위해 가능한 한 적은 단위를 참조하십시오. 특히 대화 단위와 같은 시각적 단위를 참조하지 않습니다. 예를 들어, 일반적으로 클래스 단위를 참조 할 수 없으므로 컴파일 된 DLL을 약 16KB로 줄일 수 있습니다.
2. 부름 기술.
1. 정적 메소드를 사용하는 경우 호출 된 함수 또는 프로 시저의 이름을 바꿀 수 있습니다. 위에서 언급 한 C ++로 작성된 DLL 예제에서는 외부 "C"문이 제거되면 C ++는 이상한 기능 이름을 컴파일하며 원래 Testc 함수는 @testc $ s 및 기타 우스꽝스러운 이상한 이름입니다 C ++ 이름 Mangling 기술을 사용합니다. 이 기능 이름은 Delphi에서 불법입니다.이 문제를 다음과 같이 해결할 수 있습니다.
참조 기능을 다시 작성하십시오
기능 testc (i : 정수) : 정수; stdcall;
외부 'cpp.dll'; name '@testc $ s';
이름의 기능은 이름을 바꾸는 것입니다.
2. Windows 디렉토리 또는 Windows/System 디렉토리에 우리가 쓴 DLL을 넣을 수 있습니다. 그렇게하면 외부 진술이나 loadlibrary 문에 경로를 쓰지 않고 DLL의 이름 만 쓸 수 있습니다. 그러나이 두 디렉토리에 많은 중요한 시스템 DLL이 있습니다 당신이 쓴 dlls를 시스템 디렉토리에 넣습니다!
3. 디버깅 기술.
1. 우리는 DLL을 작성할 때 단계별로 DLL을 실행하고 디버깅 할 수 없다는 것을 알고 있습니다. 이를 수행하는 방법이 있습니다. 즉, 실행 | 매개 변수 메뉴에서 호스트 프로그램을 설정합니다. 단계별 디버깅, 중단 점 관찰 및 실행을 수행하려면 로컬 페이지의 호스트 애플리케이션 막대에 호스트 프로그램의 이름을 추가하십시오.
2. DLL 버전 정보를 추가하십시오. 오프닝 비고는 버전 정보가 DLL에 매우 중요하다고 언급했습니다. 그런 작은 공간을 추가 할 가치가 있습니다. 불행히도, 프로젝트 옵션 옵션을 직접 사용할 수는 없습니다. 델파이의 도움말 파일에서는 언급되지 않았습니다. 다음 예에서 볼 수 있듯이 :
도서관 델파이;
용도
sysutils,
수업;
{$ r *.res}
// 위의 코드 줄 은이 위치에 추가되어야합니다.
함수 testdll (i : 정수) : 정수; stdcall;
시작하다
결과 : = i;
끝;
수출
testdll;
시작하다
끝.
3. 다른 DLL으로 이름을 복제하지 않기 위해서는 DLL을 쓴 DLL을 명명 할 때 혼합 문자, 숫자 및 밑줄을 사용하는 것이 가장 좋습니다. 예를 들어 : JL_TRY16.dll.
4. 이미 Delphi 1 또는 Delphi 2에서 일부 DLL을 컴파일 한 경우 컴파일 된 DLL은 16 비트입니다. New Delphi 3 또는 Delphi 4 환경에서 소스 코드를 다시 컴파일하면 32 비트 DLL을 얻을 수 있습니다.
[Note af 예를 들어, Windows에서 아이콘을 변경하는 것은 사용 된 DLL의 리소스입니다. 또한 DLL 디자인 기술을 마스터 한 후에는 고급 OLE, COM 및 ActiveX 프로그래밍을 사용하는 데 많은 이점이 있습니다.