vc delphi 回呼函數具體說明和執行個體與分析 – 轉

來源:互聯網
上載者:User

回呼函數是一個很有用,也很重要的概念。

  當發生某種事件時,系統或其他函數將會自動調用你定義的一段函數。回呼函數在windows編程使用的場合很多,比如Hook回呼函數:MouseProc,GetMsgProc以及EnumWindows,DrawState的回呼函數等等,還有很多系統級的回調過程。本文不準備介紹這些函數和過程,而是談談實現自己的回呼函數的一些經驗。

      之所以產生使用回呼函數這個想法,是因為現在使用VC和Delphi混合編程,用VC寫的一個DLL程式進行一些時間比較長的非同步工作,工作完成之後,需要通知使用DLL的應用程式:某些事件已經完成,請處理事件的後續部分。開始想過使用同步對象,檔案影射,訊息等實現DLL函數到應用程式的通知,後來突然想到可不可以在應用程式端先寫一個函數,等需要處理後續事宜的時候,在DLL裡直接調用這個函數即可。

      於是就動手,寫了個回呼函數的原形。在VC和 Delphi裡都進行了測試
      一:聲明回呼函數類型。
      vc版
      typedef int (WINAPI *PFCALLBACK)(int Param1,int Param2) ;

      Delph版

      PFCALLBACK = function(Param1:integer;Param2:integer):integer;stdcall;

    實際上是聲明了一個傳回值為int,傳入參數為兩個int的指向函數的指標。

      由於C++和PASCAL編譯器對參數入棧和函數返回的處理有可能不一致,把函數類型用WINAPI(WINAPI宏展開就是__stdcall)或stdcall統一修飾。

      二:聲明回呼函數原形

      聲明函數原形

      vc版

      int WINAPI CBFunc(int Param1,int Param2);

      Delphi版

      function CBFunc(Param1,Param2:integer):integer;stdcall;
      以上函數為全域函數,如果要使用一個類裡的函數作為回呼函數原形,把該類函式宣告為靜態函數即可。

      三: 回呼函數調用調用者
      調用回呼函數的函數我把它放到了DLL裡,這是一個很簡單的VC產生的WIN32 DLL.並使用DEF檔案輸出其函數名
      TestCallBack。實現如下:

      PFCALLBACK gCallBack=0;

      void WINAPI TestCallBack(PFCALLBACK Func)

      {

      if(Func==NULL)return;

      gCallBack=Func;

      DWORD ThreadID=0;

     ANDLE hThread = CreateThread(

      NULL,

      NULL,

      Thread1,

      LPVOID(0),

      &ThreadID

      );

      return;

      }

      此函數的工作把傳入的 PFCALLBACK Func參數儲存起來等待使用,並且啟動一個線程。聲明了一個函數指標PFCALLBACK
      gCallBack儲存傳入的函數地址。

      四: 回呼函數如何被使用:

      TestCallBack函數被調用後,啟動了一個線程,作為示範,線程人為的進行了延時處理,並且把線程啟動並執行過程列印在螢幕上.

      本段線程的代碼也在DLL工程裡實現

 

      ULONG WINAPI Thread1(LPVOID Param)

      {

      TCHAR Buffer[256];

      HDC hDC = GetDC(HWND_DESKTOP);

      int Step=1;

      MSG Msg;

      DWORD StartTick;

      //一個延時迴圈

      for(;Step<200;Step++)

      {

      StartTick = GetTickCount();

      /*這一段為線程交出部分已耗用時間以讓系統處理其他事務*/

      for(;GetTickCount()-StartTick<10;)

      {

      if(PeekMessage(&Msg,NULL,0,0,PM_NOREMOVE) )

      {

      TranslateMessage(&Msg);

      DispatchMessage(&Msg);

      }

      }

      /*把運行情況列印到案頭,這是vcbear偵錯工具時最喜歡乾的事情*/

      sprintf(Buffer,"Running %04d",Step);

      if(hDC!=NULL)

      TextOut(hDC,30,50,Buffer,strlen(Buffer));

      }

      /*延時一段時間後調用回呼函數*/

      (*gCallback)(Step,1);

      /*結束*/

      ::ReleaseDC (HWND_DESKTOP,hDC);

      return 0;

      }

      五:萬事具備

      使用vc和Delphi各建立了一個工程,編寫回呼函數的實現部分

      VC版

      int WINAPI CBFunc(int Param1,int Param2)

      {

      int res= Param1+Param2;

      TCHAR Buffer[256]="";

      sprintf(Buffer,"callback result = %d",res);

      MessageBox(NULL,Buffer,"Testing",MB_OK); //示範回呼函數被調用

      return res;

      }

      Delphi版

      function CBFunc(Param1,Param2:integer):integer;

     begin

      result:= Param1+Param2;

      TForm1.Edit1.Text:=inttostr(result); / /示範回呼函數被調用

      end;

      使用靜態串連的方法串連DLL裡的出口函數 TestCallBack,在工程裡添加 Button(
      對於Delphi的工程,還需要在Form1上放一個Edit控制項,預設名為Edit1)。

      響應ButtonClick事件調用 TestCallBack

      TestCallBack(CBFunc) //函數的參數CBFunc為回呼函數的地址

      函數調用建立線程後立刻返回,應用程式可以同時幹別的事情去了。現在可以看到螢幕上不停的顯示字串,表示dll裡建立的線程運行正常。一會之後,線程延時部分結束結束,vc的應用程式彈出MessageBox,表示回呼函數被調用並顯示根據Param1,Param2運算的結果,Delphi的程式edit控制項裡的文本則被改寫成Param1,Param2
      的運算結果。

      可見使用回呼函數的編程模式,可以根據不同的需求傳遞不同的回呼函數地址,或者定義各種回呼函數的原形(同時也需要改變使用回呼函數的參數和傳回值約定),實現多種回調事件處理,可以使程式的控制靈活多變,也是一種高效率的,清晰的程式模組之間的耦合方式。在一些非同步或複雜的程式系統裡尤其有用
      --
      你可以在一個模組(如DLL)裡專心實現模組核心的商務程序和技術功能,外圍的擴充的功能只給出一個回呼函數的介面,通過調用其他模組傳遞過來的回呼函數地址的方式,將後續處理無縫地交給另一個模組,隨它按自訂的方式處理。

      本文的例子使用了在DLL裡的多線程延時後調用回呼函數的方式,只是為了突出一下回呼函數的效果,其實只要是在本進程之內,都可以隨你高興可以把函數地址傳遞來傳遞去,當成回呼函數使用。

      這樣的編程模式原理非常簡單單一:就是把函數也看成一個指標一個地址來調用,沒有什麼別的複雜的東西,僅僅是編程裡的一個小技巧。至於回呼函數模式究竟能為你帶來多少好處,就看你是否使用,如何使用這種編程模式了。

 http://www.cnblogs.com/shilf/archive/2010/06/03/1750439.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.