首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi DLL 編程進階:全局內存共享實現應用程序間數據傳輸、服務端/客戶端編寫、GlobalAlloc 分配標誌

     編輯:Delphi

10.3 利用 DLL 實現數據傳輸

10.3.1 DLL 中的全局內存

Windows 規定:DLL 不擁有其打開的文件或分配的全局內存塊,這些由直接/間接調用 DLL 的應用程序擁有。應用程序結束時自動關閉文件、釋放內存。這導致保存在 DLL 全局變量中的句柄在 DLL 無感知下變非法,給其他使用該 DLL 的程序造成困難。

解決方案:文件/全局內存句柄不作 DLL 全局變量,而是作過程/函數參數傳遞,調用者負責維護。

特例:DLL 可擁有自身全局內存塊,須用 GMEM_DDESHARE 屬性分配,此類內存塊直到 DLL 顯式釋放或卸載前保持有效。此為應用程序間數據傳輸新途徑。

10.3.2 應用程序間數據傳輸步驟

  1. 編寫 DLL,擁有 GMEM_DDESHARE 分配的全局內存塊
  2. 服務端調用 DLL 寫入數據
  3. 客戶端調用 DLL 讀取數據

10.3.2.1 數據傳輸 DLL 編寫

特殊處:

  1. 定義全局句柄變量:var hMem: THandle;
  2. 導出返回句柄的函數:
function GetGlobalMem: THandle; export;
begin Result := hMem; end;
  1. 初始化代碼分配內存:
begin
  hMem := GlobalAlloc(GMEM_MOVEABLE and GMEM_DDESHARE, Num);
  if hMem = 0 then MessageDlg('Could not allocate memory', mtWarning, [mbOK], 0);
end.

GlobalAlloc 從全局堆分配內存返回句柄。兩參數:

  • 分配標誌(可組合):
標誌含義
GMEM_DDESHARE可被應用程序共享的內存
GMEM_DISCARDABLE可丟棄內存(需配合 MOVEABLE)
GMEM_FIXED固定內存
GMEM_MOVEABLE可移動內存
GMEM_NOCOMPACT堆內存不可壓縮/丟棄
GMEM_NODISCARD堆內存不可丟棄
GMEM_NOT_BANKED不可分段內存
GMEM_NOTIFY丟棄時調用 GlobalNotify
GMEM_ZEROINIT內容初始化為零

常用組合:GHND = GMEM_MOVEABLE and GMEM_ZEROINIT、GPTR = GMEM_FIXED and GMEM_ZEROINIT。第二參數為字節數(32 倍數,實際分配可能更大)。GMEM_DDESHARE 分配的內存在分配模塊終止時自動丟棄,無需 GlobalFree 顯式釋放。

10.3.2.2 服務端程序編寫

包含 DLL 調用聲明:

function GetGlobalMem: THandle; far; external 'c:\dlls\glbmem';

寫入數據前必須鎖定內存(GlobalLock),防止 Windows 移動內存位置:

var hMem: THandle; pMem: PChar;
begin
  hMem := GetGlobalMem;
  if hMem <> 0 then
  begin
    pMem := GlobalLock(hMem);
    if pMem <> nil then
    begin
      StrPCopy(pMem, Memo1.Text);  // 寫入數據
      GlobalUnlock(hMem);          // 盡早解鎖利於內存管理
    end
    else MessageDlg('Could not Lock memory block', mtWarning, [mbOK], 0);
  end;
end;

10.3.2.3 客戶端程序編寫

幾乎同服務端,差別在讀取數據:

var hMem: THandle; pMem: PChar;
begin
  hMem := GetGlobalMem;
  if hMem <> 0 then
  begin
    pMem := GlobalLock(hMem);
    if pMem <> nil then
    begin
      Memo1.Text := StrPas(pMem);  // 讀取數據
      GlobalUnlock(hMem);
    end
    else MessageDlg('Could not Lock memory block', mtWarning, [mbOK], 0);
  end;
end;
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved