본문 바로가기
IT-개발,DB

[개발/델파이] Callback 함수 구현

by SB리치퍼슨 2012. 11. 30.


Callback 함수 구현


원문출처 : http://www.delphi-central.com/callback.aspx







가이드 - Callback 프로시저 구현

소개

함수와 프로시저 Callback은 정의되지 않은 채 사용되지만 꽤 큰 잇점이 있다는 걸 안다. 예를들어 중복 코드에 대한 제한하도록 도움을 주고 코드의 판독성과 유지보수를 더 쉽게 해준다.


Callback이란

callback은 다른 프로시저로 파라메터로서 프로시저나 함수를 패싱하는 방법이다. 따라서 호출되는 프로시저내에서 이벤트가 발생하는 것을 callback이라 부르며, callback프로시저가 완료될 때, 제어가 원래의 프로시저로 넘어간다.

아래에 좋은 예제가 있다. object 배열을 갖고 있고 모두를 실행하길 원한다고 하자. 요청된 방식으로 호출하는 배열을 통해 루프를 이용하여 수행될 수 있다. 매번 모든 object를 사용하려할 때 5개의 방법을 갖고 있다고 상상해보자. 다시말해, 몇번의 복사와 붙여넣기로 쉽게 되지만 callback의 사용은 유익할 것이다. object에 대하여 루프를 이용하여 마스터 프로시저가 되도록 하고 파라메터로 object를 넘겨서 매번 callback 프로시저를 호출한다.


Callback 함수 샘플

이 샘플에서는 요청된 callback을 선언하는 방법을 보여주고 사용한다. 실제 루틴은 디렉토리 검색이고 각 파일명을 callback 함수로 호출한다.


선언

아래 unit 의 type 섹션에서 callback 프로시져를 선언해보자 

TFileCallbackProcedure = procedure(filename:string) 
                         of object;

TFileCallbackProcedure는 문자열 파라메터를 포함하는 프로시저이고 object 메소드이다. 


다음으로 callback 프로시저를 호출하는 프로시저의 선언부이다. 

Next we need to declare the procedure that will actually call the callback procedure:

Procedure RecurseDirectory(
    Dir : String;
    IncludeSubs : boolean; 
    callback : TFileCallbackProcedure);

이 프로시저는 여느 다른 프로지서와 유사하지만 파라메터 중 하나가 다른 함수를 필요로하는 type TFileCallbackProcedure 이다. 


코드

다음은 RecurseDirectory 프로시저의 구현부이다.

Procedure TForm1.RecurseDirectory(
  Dir : String;
  IncludeSubs : boolean;
  callback : TFileCallbackProcedure);
var
  SearchRec :TSearchRec;
  Result : LongInt;
begin
  Result := FindFirst(Dir+'\*.*', faAnyFile , SearchRec);
  while Result = 0 do
  begin
    { This makes sure its not the . or .. directorys}
    if not(SearchRec.name[1]='.') then
    begin
      if (SearchRec.attr and faDirectory) <> 0 then
      begin
      { its a dir so do a recursive call 
        if subdirectories wanted }
        if IncludeSubs then
          RecurseDirectory(Dir +'\' + SearchRec.name,
                           IncludeSubs, callback);
      end
      else
        { Call are callback function}
        callback(dir+'\'+SearchRec.name);
      end; //if . ..
    Result := FindNext(SearchRec);
  end;
end;
 

디렉토리를 리커시브하게 스캔하여 서브디렉토리를 callback 함수 파라메터로 넘기고 있다. 이제 RecurseDirectory 프로시저가 호출하는 callback프로시저를 작성한다.

먼저, 새 어플리케이션을 시작하고 TButton과 TListBox를 폼위에 생성한다. 이름은 그냥 디폴트 네임으로 한다. 위에 작성된 RecurseDirectory 프로시저의 선언과 구현부를 추가한다. callback 프로시저의 선언과 구현부도 private 영역에 추가한다.

   Procedure MyCallback(filename:string);

ListBox1에 파일명을 추가하는 예제이다. 

Procedure TForm1.MyCallback(filename:string);
begin
 listbox1.items.add(filename);
end;
 

마지막으로, 작성된 callback프로시저를 사용한 RescuseDirectory를 호출하는 코드를 Button1Click 이벤트에 추가한다.

procedure TForm1.Button1Click(Sender: TObject);
begin
  RecurseDirectory('c:',true,MyCallback);
end;

이제 RecurseDirectory 프로시저에 대한 작업이 완료되었고 MyCallback 이라는 callback 프로시저도 구현되었다. 

실행준비가 된 어플리케이션을 실행하여 button을 클릭할 때 listbox에 C드라이브의 경로와 파일명이 추가되는 것을 볼 수 있다. C드라이브가 크다면 꽤나 시간이 걸릴 수도 있다.


결론

이 글이 callback에 대한 정보를 찾는 개발자에게 더 유용하고 유익하게 사용되었으면 한다. 위 예제는 간단하면서도 마음에 쏙 들수 있을 것이다. 다른 샘플로는 디렉토리에서 pas파일의 수를 카운팅하거나 백업파일 삭제하기, 등등.

좀 더 모험적이라면 어플리케이션 제작시에 모든 폼에 루프를 돌려 레지스트리에 위치를 기억할 수도 있겠다. 가능성은 무한하다. 할 수 있는 것과 어떻게 할지를 알고 있는건 좋은 것이다. 

반응형

댓글