當前位置:編程學習大全網 - 源碼下載 - 求下面程序的註釋,程序能否運行?為什麽我運行不出結果呢?

求下面程序的註釋,程序能否運行?為什麽我運行不出結果呢?

兄弟,delphi2007正版還是盜版?哪兒弄的?能否告知壹下?

壹、開使妳的第壹個DLL專案

1.File->Close all->File->New〔DLL〕

代碼:

//自動產生Code如下

library Project2;

//這有段廢話

uses

SysUtils,

Classes;

begin

end.

2.加個Func進來:

代碼:

library Project2;

uses

SysUtils,

Classes;

Function MyMax ( X , Y : integer ) : integer ; stdcall ;

begin

if X > Y then

Result := X

else

Result := Y ;

end ;

//切記:Library 的名字大小寫沒關系,可是DLL-Func的大小寫就有關系了。

// 在 DLL-Func-Name寫成MyMax與myMAX是不同的。如果寫錯了,立即

// 的結果是妳叫用到此DLL的AP根本開不起來。

//參數的大小寫就沒關系了。甚至不必同名。如原型中是 (X,Y:integer)但引

// 用時寫成(A,B:integer),那是沒關系的。

//切記:要再加個stdcall。書上講,如果妳是用Delphi寫DLL,且希望不僅給

// Delphi-AP也希望BCB/VC-AP等使用的話,那妳最好加個Stdcall ; 的指示

//參數型態:Delphi有很多種它自己的變量型態,這些當然不是DLL所喜歡的

// ,Windows/DLL的母語應該是C。所以如果要傳進傳出DLL的參數,我們

// 盡可能照規矩來用。這兩者寫起來,後者會麻煩不少。如果妳對C不熟

// 的話,那也沒關系。我們以後再講。

begin

end.

3.將這些可***享的Func送出DLL,讓外界〔就是妳的Delphi-AP啦〕使用:光如此,妳的AP還不能用到這些,妳還要加個Exports才行。

代碼:

exports

MyMax ;

begin

end.

4.好了,可以按 Ctrl-F9編譯了。此時可不要按F9。DLL不是EXE┌不可單獨執行的,如果妳按F9,會有ErrorMsg的。這時如果DLL有Error,請修正之。再按Ctrl-F9。此時可能有Warning,不要緊,研究壹下,看看就好。再按Ctrl-F9,此時就『Done , Compiled 』。同目錄就會有個 *.dll 。恭喜,大功告成了。

二、進行測試:開個新application:

1.加個TButton

代碼:

ShowMessage ( IntToStr(MyMax(30,50)) ) ;

2.告知Exe到那裏抓個Func

代碼:

//在Form,interface,var後加

Function MyMax ( X , Y : integer ) : integer ; stdcall ; external 'MyTestDLL.dll' ;

// MyTestDLL.dll為妳前時寫的DLL項目名字

// DLL名字大小寫沒關系。不過記得要加 extension的 .DLL。在Win95或NT,

// 是不必加 extension,但這兩種OS,可能越來越少了吧。要加extension

可以了,簡單吧。

上面的例子是不是很簡單?熟悉Delphi的朋友可以看出以上代碼和壹般的Delphi程序的編寫基本是相同的,只是在TestDll函數後多了壹個stdcall參數並且用exports語句聲明了TestDll函數。只要編譯上面的代碼,就可以玫揭桓雒?狣elphi.dll的動態鏈接庫。現在,讓我們來看看有哪些需要註意的地方:

1.在DLL中編寫的函數或過程都必須加上stdcall調用參數。在Delphi 1或Delphi 2環境下該調用參數是far。從Delphi 3以後將這個參數變為了stdcall,目的是為了使用標準的Win32參數傳遞技術來代替優化的register參數。忘記使用stdcall參數是常見的錯誤,這個錯誤不會影響DLL的編譯和生成,但當調用這個DLL時會發生很嚴重的錯誤,導致操作系統的死鎖。原因是register參數是Delphi的默認參數。

2.所寫的函數和過程應該用exports語句聲明為外部函數。

正如大家看到的,TestDll函數被聲明為壹個外部函數。這樣做可以使該函數在外部就能看到,具體方法是單激鼠標右鍵用“快速查看(Quick View)”功能查看該DLL文件。(如果沒有“快速查看”選項可以從Windows CD上安裝。)TestDll函數會出現在Export Table欄中。另壹個很充分的理由是,如果不這樣聲明,我們編寫的函數將不能被調用,這是大家都不願看到的。

3.當使用了長字符串類型的參數、變量時要引用ShareMem。

Delphi中的string類型很強大,我們知道普通的字符串長度最大為256個字符,但Delphi中string類型在默認情況下長度可以達到2G。(對,您沒有看錯,確實是兩兆。)這時,如果您堅持要使用string類型的參數、變量甚至是記錄信息時,就要引用ShareMem單元,而且必須是第壹個引用的。既在uses語句後是第壹個引用的單元。如下例:

uses

ShareMem,

SysUtils,

Classes;

還有壹點,在您的工程文件(*.dpr)中而不是單元文件(*.pas)中也要做同樣的工作,這壹點Delphi自帶的幫助文件沒有說清楚,造成了很多誤會。不這樣做的話,您很有可能付出死機的代價。避免使用string類型的方法是將string類型的參數、變量等聲明為Pchar或ShortString(如:s:string[10])類型。同樣的問題會出現在當您使用了動態數組時,解決的方法同上所述。

在Delphi中靜態調用DLL top

調用壹個DLL比寫壹個DLL要容易壹些。首先給大家介紹的是靜態調用方法,稍後將介紹動態調用方法,並就兩種方法做壹個比較。同樣的,我們先舉壹個靜態調用的例子。

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics,

Controls, Forms, Dialogs, StdCtrls;

type

TForm1 = class(TForm)

Edit1: TEdit;

Button1: TButton;

procedure Button1Click(Sender: TObject);

private

public

end;

var

Form1: TForm1;

implementation

//本行以下代碼為我們真正動手寫的代碼

function TestDll(i:integer):integer;stdcall;

external ’Delphi.dll’;

procedure TForm1.Button1Click(Sender: TObject);

begin

Edit1.Text:=IntToStr(TestDll(1));

end;

end.

上面的例子中我們在窗體上放置了壹個編輯框(Edit)和壹個按鈕(Button),並且書寫了很少的代碼來測試我們剛剛編寫的Delphi.dll。大家可以看到我們唯壹做的工作是將TestDll函數的說明部分放在了implementation中,並且用external語句指定了Delphi.dll的位置。(本例中調用程序和Delphi.dll在同壹個目錄中。)讓人興奮的是,我們自己編寫的TestDll函數很快被Delphi認出來了。您可做這樣壹個實驗:輸入“TestDll(”,很快Delphi就會用fly-by提示條提示您應該輸入的參數是什麽,就像我們使用Delphi中定義的其他函數壹樣簡單。註意事項有以下壹些:

壹、調用參數用stdcall

和前面提到的壹樣,當引用DLL中的函數和過程時也要使用stdcall參數,原因和前面提到的壹樣。

二、用external語句指定被調用的DLL文件的路徑和名稱

正如大家看到的,我們在external語句中指定了所要調用的DLL文件的名稱。沒有寫路徑是因為該DLL文件和調用它的主程序在同壹目錄下。如果該DLL文件在C:\,則我們可將上面的引用語句寫為external ’C:\Delphi.dll’。註意文件的後綴.dll必須寫上。

三、不能從DLL中調用全局變量

如果我們在DLL中聲明了某種全局變量,如:var s:byte 。這樣在DLL中s這個全局變量是可以正常使用的,但s不能被調用程序使用,既s不能作為全局變量傳遞給調用程序。不過在調用程序中聲明的變量可以作為參數傳遞給DLL。

四、被調用的DLL必須存在

這壹點很重要,使用靜態調用方法時要求所調用的DLL文件以及要調用的函數或過程等等必須存在。如果不存在或指定的路徑和文件名不正確的話,運行主程序時系統會提示“啟動程序時出錯”或“找不到*.dll文件”等運行錯誤。

在Delphi中動態調用DLL top

動態調用DLL相對復雜很多,但非常靈活。為了全面的說明該問題,這次我們舉壹個調用由C++編寫的DLL的例子。首先在C++中編譯下面的DLL源程序。

#include

extern ”C” _declspec(dllexport)

int WINAPI TestC(int i)

{

return i;

}

編譯後生成壹個DLL文件,在這裏我們稱該文件為Cpp.dll,該DLL中只有壹個返回整數類型的函數TestC。為了方便說明,我們仍然引用上面的調用程序,只是將原來的Button1Click過程中的語句用下面的代碼替換掉了。

procedure TForm1.Button1Click(Sender: TObject);

type

TIntFunc=function(i:integer):integer;stdcall; //去掉dll中的函數名既可

var

Th:Thandle;

Tf:TIntFunc;

Tp:TFarProc;

begin

Th:=LoadLibrary(’Cpp.dll’);

if Th>0 then

try

Tp:=GetProcAddress(Th,PChar(’TestC’));

if Tp<>nil

then begin

Tf:=TIntFunc(Tp);

Edit1.Text:=IntToStr(Tf(1));

end

else

ShowMessage(’TestC函數沒有找到’);

finally

FreeLibrary(Th);

end

else

ShowMessage(’Cpp.dll沒有找到’);

end;

大家已經看到了,這種動態調用技術很復雜,但只要修改參數,如修改LoadLibrary(’Cpp.dll’)中的DLL名稱為’Delphi.dll’就可動態更改所調用的DLL。

壹、定義所要調用的函數或過程的類型

在上面的代碼中我們定義了壹個TIntFunc類型,這是對應我們將要調用的函數TestC的。在其他調用情況下也要做同樣的定義工作。並且也要加上stdcall調用參數。

二、釋放所調用的DLL

我們用LoadLibrary動態的調用了壹個DLL,但要記住必須在使用完後手動地用FreeLibrary將該DLL釋放掉,否則該DLL將壹直占用內存直到您退出Windows或關機為止。

現在我們來評價壹下兩種調用DLL的方法的優缺點。靜態方法實現簡單,易於掌握並且壹般來說稍微快壹點,也更加安全可靠壹些;但是靜態方法不能靈活地在運行時裝卸所需的DLL,而是在主程序開始運行時就裝載指定的DLL直到程序結束時才釋放該DLL,另外只有基於編譯器和鏈接器的系統(如Delphi)才可以使用該方法。動態方法較好地解決了靜態方法中存在的不足,可以方便地訪問DLL中的函數和過程,甚至壹些老版本DLL中新添加的函數或過程;但動態方法難以完全掌握,使用時因為不同的函數或過程要定義很多很復雜的類型和調用方法。對於初學者,筆者建議您使用靜態方法,待熟練後再使用動態調用方法。

使用DLL的實用技巧 top

壹、編寫技巧

1 、為了保證DLL的正確性,可先編寫成普通的應用程序的壹部分,調試無誤後再從主程序中分離出來,編譯成DLL。

2 、為了保證DLL的通用性,應該在自己編寫的DLL中杜絕出現可視化控件的名稱,如:Edit1.Text中的Edit1名稱;或者自定義非Windows定義的類型,如某種記錄。

3 、為便於調試,每個函數和過程應該盡可能短小精悍,並配合具體詳細的註釋。

4 、應多利用try-finally來處理可能出現的錯誤和異常,註意這時要引用SysUtils單元。

5 、盡可能少引用單元以減小DLL的大小,特別是不要引用可視化單元,如Dialogs單元。例如壹般情況下,我們可以不引用Classes單元,這樣可使編譯後的DLL減小大約16Kb。

二、調用技巧

1 、在用靜態方法時,可以給被調用的函數或過程更名。在前面提到的C++編寫的DLL例子中,如果去掉extern ”C”語句,C++會編譯出壹些奇怪的函數名,原來的TestC函數會被命名為@TestC$s等等可笑的怪名字,這是由於C++采用了C++ name mangling技術。這個函數名在Delphi中是非法的,我們可以這樣解決這個問題:

改寫引用函數為

function TestC(i:integer):integer;stdcall;

external ’Cpp.dll’;name ’@TestC$s’;

其中name的作用就是重命名。

2 、可把我們編寫的DLL放到Windows目錄下或者Windows\system目錄下。這樣做可以在external語句中或LoadLibrary語句中不寫路徑而只寫DLL的名稱。但這樣做有些不妥,這兩個目錄下有大量重要的系統DLL,如果您編的DLL與它們重名的話其後果簡直不堪設想,況且您的編程技術還不至於達到將自己編寫的DLL放到系統目錄中的地步吧!

三、調試技巧

1 、我們知道DLL在編寫時是不能運行和單步調試的。有壹個辦法可以,那就是在Run|parameters菜單中設置壹個宿主程序。在Local頁的Host Application欄中添上宿主程序的名字就可進行單步調試、斷點觀察和運行了。

2 、添加DLL的版本信息。開場白中提到了版本信息對於DLL是很重要的,如果包含了版本信息,DLL的大小會增加2Kb。增加這麽壹點空間是值得的。很不幸我們如果直接使用Project|options菜單中Version選項是不行的,這壹點Delphi的幫助文件中沒有提到,經筆者研究發現,只要加壹行代碼就可以了。如下例:

我們在用Delphi編譯完程序,準備發布產品時,總希望隨產品發布個性信息以標示產品的來源

以及開發者等信息,就像windows的程序壹樣,使我們壹看屬性就知道他是微軟的產品,這些在

Delphi中是如何實現的呢?下面我就來給大家演示和說明給exe,dll文件添加版本信息的方法。

VS_VERSION_INFO VERSIONINFO //版本信息結構

FILEVERSION 1,0,0,1 //顧名思義文件版本,就是在屬性頁版本上面顯示的|

PRODUCTVERSION 1,0,0,1 //顧名思義產品版本 |這裏是主版本信息

FILEFLAGSMASK 0x3fL //這裏設為0x3fL就好了 |

#ifdef _DEBUG

FILEFLAGS 0x1L //VS_FF_DEBUG包括debug信息

#else

FILEFLAGS 0x0L //無

#endif

FILEOS 0x4L //對應於delphi中VOS__WINDOWS32,說明程序是win32程序

FILETYPE 0x2L //文件類型,$2是dll,$1是exe

FILESUBTYPE 0x0L //文件子類型,壹般設為0即可

BEGIN

BLOCK StringFileInfo //這裏設置文件其他的版本信息(詳細信息)

BEGIN

BLOCK 080403A8 //所用語言080403A8簡體中文,040904b0英語(美國)

BEGIN

VALUE Comments, My Dll Application test //備註

VALUE CompanyName, JJony\0 //公司名

VALUE FileDescription, xxx.dll\0 //產品描述

VALUE FileVersion, 1. 0. 0. 1\0 //文件版本

VALUE InternalName, //內部名稱

VALUE LegalCopyright, Copyright (C) 2006.6\0 //版權信息

VALUE OriginalFilename, xxx.dll\0 //源文件名

VALUE ProductName, xxx.dll\0 //產品名

VALUE ProductVersion, 1. 0. 0. 1\0 //產品版本

END

END

BLOCK VarFileInfo

BEGIN

VALUE Translation, 0x804, 0x03A8 //這裏是關鍵哦,決定了是什麽語言

END //0x0804, 0x03A8簡體中文

END //0x0409, 0x04b0英語(美國)

壹種更為簡單的添加DLL的版本信息的方法是:

先將壹個要引用dll文件的程序的版本信息添加全面,然後將該程序的Project1.res復制到要產生dll的文件目錄下,並改名為aa.res,然後制做dll,將dll編輯器中"library Project1"改為"library aa",添加“”,編譯,OK了。

3 、為了避免與別的DLL重名,在給自己編寫的DLL起名字的時候最好采用字符數字和下劃線混合的方式。如:jl_try16.dll。

4 、如果您原來在Delphi 1或Delphi 2中已經編譯了某些DLL的話,您原來編譯的DLL是16位的。只要將源代碼在新的Delphi 3或Delphi 4環境下重新編譯,就可以得到32位的DLL了。

[後記]:除了上面介紹的DLL最常用的使用方法外,DLL還可以用於做資源的載體。例如,在Windows中更改圖標就是使用的DLL中的資源。另外,熟練掌握了DLL的設計技術,對使用更為高級的OLE、COM以及ActiveX編程都有很多益處

  • 上一篇:計算機桌面無法顯示設定的壁紙。
  • 下一篇:蘭州市軟件開發哪家公司做得好
  • copyright 2024編程學習大全網