10.3 利用DLLs實(shí)現(xiàn)數(shù)據(jù)傳輸
10.3.1 DLLs中的全局內(nèi)存
Windows規(guī)定:DLLs并不擁有它打開的任何文件或它分配的任何全局內(nèi)存塊。這些對象由直接或間接調(diào)用DLLs的應(yīng)用程序擁有。這樣,當(dāng)應(yīng)用程序中止時,它擁有的打開的文件自動關(guān)閉,它擁有的全局內(nèi)存塊自動釋放。這就意味著保存在DLLs全局變量中的文件和全局內(nèi)存塊變量在DLLs沒有被通知的情況下就變?yōu)榉欠ā_@將給其它使用該DLLs的應(yīng)用程序造成困難。
為了避免出現(xiàn)這種情況,文件和全局內(nèi)存塊句柄不應(yīng)作為DLLs的全局變量,而是作為DLLs中過程或函數(shù)的參數(shù)傳遞給DLLs使用。調(diào)用DLLs的應(yīng)用程序應(yīng)該負(fù)責(zé)對它們的維護(hù)。
但在特定情況下,DLLs也可以擁有自己的全局內(nèi)存塊。這些內(nèi)存塊必須用gmem_DDEShare屬性進(jìn)行分配。這樣的內(nèi)存塊直到被DLLs顯示釋放或DLLs退出時都保持有效。
由DLLs管理的全局內(nèi)存塊是應(yīng)用程序間進(jìn)行數(shù)據(jù)傳輸?shù)挠忠煌緩?,下面我們將專門討論這一問題。
10.3.2 利用DLLs實(shí)現(xiàn)應(yīng)用程序間的數(shù)據(jù)傳輸
利用DLLs實(shí)現(xiàn)應(yīng)用程序間的數(shù)據(jù)傳輸?shù)牟襟E為:
1. 編寫一個DLLs程序,其中擁有一個用gmem_DDEShare屬性分配的全局內(nèi)存塊;
2. 服務(wù)器程序調(diào)用DLLs,向全局內(nèi)存塊寫入數(shù)據(jù);
3. 客戶程序調(diào)用DLLs,從全局內(nèi)存塊讀取數(shù)據(jù)。
10.3.2.1 用于實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)腄LLs的編寫
用于實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)腄LLs與一般DLLs的編寫基本相同,其中特別的地方是:
1. 定義一個全局變量句柄:
var
hMem: THandle;
2. 定義一個過程,返回該全局變量的句柄。該過程要包含在exports子句中。如:
function GetGlobalMem: THandle; export;
begin
Result := hMem;
end;
3. 在初始化代碼中分配全局內(nèi)存塊:
程序清單如下:
begin
hMem := GlobalAlloc(gmem_MOVEABLE and gmem_DDEShare,num);
if hMem = 0 then
MessageDlg('Could not allocate memory',mtWarning,[mbOK],0);
end.
num是一個預(yù)定義的常數(shù)。
Windows API函數(shù)GlobalAlloc用于從全局內(nèi)存堆中分配一塊內(nèi)存,并返回該內(nèi)存塊的句柄。該函數(shù)包括兩個參數(shù),第一個參數(shù)用于設(shè)置內(nèi)存塊的分配標(biāo)志??梢允褂玫姆峙錁?biāo)志如下表所示。
表10.3 全局內(nèi)存塊的分配標(biāo)志
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
標(biāo) 志 意 義
—————————————————————————————————
gmem_DDEShare 分配可由應(yīng)用程序共享的內(nèi)存
gmem_Discardable 分配可拋棄的內(nèi)存(只與gmem_Moveable連用)
gmem_Fixed 分配固定內(nèi)存
gmem_Moveable 分配可移動的內(nèi)存
gmem_Nocompact 該全局堆中的內(nèi)存不能被壓縮或拋棄
gmem_Nodiscard 該全局堆中的內(nèi)存不能被拋棄
gmem_NOT_Banked 分配不能被分段的內(nèi)存
gmem_Notify 通知功能。當(dāng)該內(nèi)存被拋棄時調(diào)用GlobalNotify函數(shù)
gmem_Zeroinit 將所分配內(nèi)存塊的內(nèi)容初始化為零
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
有兩個預(yù)定義的常用組合是:
GHND = gmem_Moveable and gmem_Zeroinit
GPTK = gmem_Fixed and gmem_Zeroinit
第二個參數(shù)用于設(shè)置欲分配的字節(jié)數(shù)。分配的字節(jié)數(shù)必須是32的倍數(shù),因而實(shí)際分配的字節(jié)數(shù)可能比所設(shè)置的要大。
由于用gmem_DDEShare分配的內(nèi)存在分配內(nèi)存的模塊終止時自動拋棄,因而不必調(diào)用GlobalFree顯式釋放內(nèi)存。
10.3.1 DLLs中的全局內(nèi)存
Windows規(guī)定:DLLs并不擁有它打開的任何文件或它分配的任何全局內(nèi)存塊。這些對象由直接或間接調(diào)用DLLs的應(yīng)用程序擁有。這樣,當(dāng)應(yīng)用程序中止時,它擁有的打開的文件自動關(guān)閉,它擁有的全局內(nèi)存塊自動釋放。這就意味著保存在DLLs全局變量中的文件和全局內(nèi)存塊變量在DLLs沒有被通知的情況下就變?yōu)榉欠ā_@將給其它使用該DLLs的應(yīng)用程序造成困難。
為了避免出現(xiàn)這種情況,文件和全局內(nèi)存塊句柄不應(yīng)作為DLLs的全局變量,而是作為DLLs中過程或函數(shù)的參數(shù)傳遞給DLLs使用。調(diào)用DLLs的應(yīng)用程序應(yīng)該負(fù)責(zé)對它們的維護(hù)。
但在特定情況下,DLLs也可以擁有自己的全局內(nèi)存塊。這些內(nèi)存塊必須用gmem_DDEShare屬性進(jìn)行分配。這樣的內(nèi)存塊直到被DLLs顯示釋放或DLLs退出時都保持有效。
由DLLs管理的全局內(nèi)存塊是應(yīng)用程序間進(jìn)行數(shù)據(jù)傳輸?shù)挠忠煌緩?,下面我們將專門討論這一問題。
10.3.2 利用DLLs實(shí)現(xiàn)應(yīng)用程序間的數(shù)據(jù)傳輸
利用DLLs實(shí)現(xiàn)應(yīng)用程序間的數(shù)據(jù)傳輸?shù)牟襟E為:
1. 編寫一個DLLs程序,其中擁有一個用gmem_DDEShare屬性分配的全局內(nèi)存塊;
2. 服務(wù)器程序調(diào)用DLLs,向全局內(nèi)存塊寫入數(shù)據(jù);
3. 客戶程序調(diào)用DLLs,從全局內(nèi)存塊讀取數(shù)據(jù)。
10.3.2.1 用于實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)腄LLs的編寫
用于實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)腄LLs與一般DLLs的編寫基本相同,其中特別的地方是:
1. 定義一個全局變量句柄:
var
hMem: THandle;
2. 定義一個過程,返回該全局變量的句柄。該過程要包含在exports子句中。如:
function GetGlobalMem: THandle; export;
begin
Result := hMem;
end;
3. 在初始化代碼中分配全局內(nèi)存塊:
程序清單如下:
begin
hMem := GlobalAlloc(gmem_MOVEABLE and gmem_DDEShare,num);
if hMem = 0 then
MessageDlg('Could not allocate memory',mtWarning,[mbOK],0);
end.
num是一個預(yù)定義的常數(shù)。
Windows API函數(shù)GlobalAlloc用于從全局內(nèi)存堆中分配一塊內(nèi)存,并返回該內(nèi)存塊的句柄。該函數(shù)包括兩個參數(shù),第一個參數(shù)用于設(shè)置內(nèi)存塊的分配標(biāo)志??梢允褂玫姆峙錁?biāo)志如下表所示。
表10.3 全局內(nèi)存塊的分配標(biāo)志
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
標(biāo) 志 意 義
—————————————————————————————————
gmem_DDEShare 分配可由應(yīng)用程序共享的內(nèi)存
gmem_Discardable 分配可拋棄的內(nèi)存(只與gmem_Moveable連用)
gmem_Fixed 分配固定內(nèi)存
gmem_Moveable 分配可移動的內(nèi)存
gmem_Nocompact 該全局堆中的內(nèi)存不能被壓縮或拋棄
gmem_Nodiscard 該全局堆中的內(nèi)存不能被拋棄
gmem_NOT_Banked 分配不能被分段的內(nèi)存
gmem_Notify 通知功能。當(dāng)該內(nèi)存被拋棄時調(diào)用GlobalNotify函數(shù)
gmem_Zeroinit 將所分配內(nèi)存塊的內(nèi)容初始化為零
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
有兩個預(yù)定義的常用組合是:
GHND = gmem_Moveable and gmem_Zeroinit
GPTK = gmem_Fixed and gmem_Zeroinit
第二個參數(shù)用于設(shè)置欲分配的字節(jié)數(shù)。分配的字節(jié)數(shù)必須是32的倍數(shù),因而實(shí)際分配的字節(jié)數(shù)可能比所設(shè)置的要大。
由于用gmem_DDEShare分配的內(nèi)存在分配內(nèi)存的模塊終止時自動拋棄,因而不必調(diào)用GlobalFree顯式釋放內(nèi)存。