讀書 – Delphi下深入Windows核心編程 第一天

來源:互聯網
上載者:User

技術交流,DH講解.

晚上突然有這個想法,該踏踏實實把所有的書讀一遍,好吧.踏實一些.
這本書,我也只有電子版,要下的人可以去盒子,園地還有我的網盤都有.

第一章 DLL和資料共用
首先建立一個DLL工程:


匯出函數的2種方式:

function Export1():Integer ; export;begin  //add code hereend;

就是在函數後面寫個export.

function Export1():Integer ;begin  //add code hereend;function Export2():Cardinal ;stdcall;begin  //add code hereend;exports  Export1,Export2;

exports後面把所有要匯出的函數名字寫上.
exe調用Dll也有2種方式:
顯式調用:

function Export1():Integer;external 'Project2.dll';implementation

定義一個函數,然後external 說明這個函數來之哪個dll.這樣就不用實現了.
隱式調用:

type  TExport2 = function : Cardinal;stdcall;procedure TForm1.FormCreate(Sender: TObject);var  hLib:Cardinal;  Export2:TExport2;begin  hLib:=LoadLibrary('Project2.dll');  Export2:=TExport2(GetProcAddress(hLib,'Export2'));  //執行函數  Export2;  FreeLibrary(hLib);end;

先用LoadLibary載入Dll然後GetProcAddress來取得函數指標,然後執行,最後釋放dll控制代碼,記得.
既然說到了調用,這裡就要說呼叫慣例了:
            register       函數體      從左至右,優先使用寄存器(EAX,EDX,ECX),然後使用堆棧
            pascal         函數體      從左至右,通過堆棧傳遞
            cdecl           調用者      從右至左,通過堆棧傳遞(與C\C++預設呼叫慣例相容)
            stdcall         函數體      從右至左,通過堆棧傳遞(與VC中的__stdcall相容)
            safecall       函數體      從右至左,通過堆棧傳遞(同stdcall)

我們看見傳參不一樣我調用的方式要是不一樣,那麼參數就可能不對了,函數最後的結果肯定不一樣了.
如果我們想在Dll初始化幹點兒事,結束時幹點兒事,怎麼辦?

//Dll工程檔案的末尾的Begin End中間begin  //這裡寫代碼就是初始化了,但是這樣只能初始化幹事情end.

只能初始化...那怎麼辦?
解決方案又有2個,哈哈:
第一個,我們添加一個引用單元,然後這個單元initialization和finalization進行初始化和收尾工作塞.

uses  Unit2 in 'Unit2.pas';//Dll添加引用單元
unit Unit2;interfaceuses  SysUtils;implementationvar  L:TObject;initialization  L:=TObject.Create;//初始化工作finalization  L.Free; //收尾工作end.

第二個,調用main函數,是的,dllmain(),不過Delphi裡面不是叫這個,叫dllproc().

procedure MyDllMain(n:Integer);begin  case n of    DLL_PROCESS_ATTACH:      begin        //進程載入Dll的時候      end;    DLL_PROCESS_DETACH:      begin        //進程卸載Dll的時候      end;    DLL_THREAD_ATTACH:      begin        //線程載入Dll的時候      end;    DLL_THREAD_DETACH:      begin        //線程卸載Dll的時候      end;  end;end;begin  DllProc:=MyDllMain;  MyDllMain(DLL_PROCESS_ATTACH);end.

當Dll被一個進程載入之後,DLL的變數的空間就是這個進程裡面了.也就是如果2個進程載入一個DLL,那麼DLL的全域變數就有2個備份了,互不相干,是吧.
要多個DLL共用一個全域變數怎麼辦?接下來要說的就是用記憶體對應檔.

type  TData = record    A:Integer;    //其他資料  end;  PData = ^TData;var  hMap:Cardinal;  data:PData;procedure MyDllMain(n:Integer);begin  case n of    DLL_PROCESS_ATTACH:      begin        hMap:=OpenFileMapping(FILE_MAP_ALL_ACCESS,False,'名字');        if hMap = 0 then//沒有就建立        begin          //記憶體映射的話,第一個參數必須是$FFFFFFFF,檔案對應的話就是檔案控制代碼          //第二個參數:安全,一般為nil          //第三個參數:對應檔的屬性,我們要可讀可寫          //第四個參數:要映射資料大小的高4個位元組          //第五個參數:要映射資料大小的低4個位元組          //第六個參數:唯一的名字          hMap:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,SizeOf(TData),'名字');          if hMap=0 then//建立失敗            Exit;        end;        //映射資料        data:=MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,0);//全部映射出來        if data = nil then//映射失敗          Exit;      end;    DLL_PROCESS_DETACH:      begin        if Boolean(data) then        begin          UnmapViewOfFile(data);          CloseHandle(hMap);        end;      end;  end;end;

現在就映射好了,只要對data進行操作就會寫到共用記憶體區了.因為可能多個DLL回去寫,所以這裡我們需要弄個互斥對象來同步.我就不示範了.這書上的代碼裡面會有的.
還有一個地方,映射的時候都只有一個變數一個結構體,結構體裡面不要有指標,也就是像String這樣的,因為指標指向的地址又是在進程空間中了.如果有多個結構體要共用,就需要先把多個結構體定義成一個結構體.

其他共用資料的方式:
1 SendMessage 或者 PostMessage,然後靠LPARAM和WPARAM來傳遞,但是LPARAM和WPARAM只是2個Integer,也就是傳遞的資料也就只有2個數,地址,指標沒戲,因為你指標還是進程空間裡面的,沒有映射出來.
2 WM_COPYDATA訊息可以傳一個指標出來.

function SendCopyData(h:HWND;s:AnsiString):Integer ;var  p:PAnsiChar;  bufsize:Integer;  data:TCopyDataStruct;begin  bufsize:=Length(s) + 1;  p:=AllocMem(bufsize);  StrCopy(p,PAnsiChar(s));  with data do  begin    cbData:=bufsize;    dwData:=12315;//自己定義    lpData:=p;  end;  Result:=SendMessage(h,WM_COPYDATA,0,Integer(@data))end;

好的第一章就這樣,準備睡覺.明天不能遲到了...

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.