프로그래밍

CallBack func

지니아부지 2012. 7. 24. 16:50
출처 : http://smok95.tistory.com/193

콜백함수란 어떠한 정보(또는 이벤트)를 관리하는 대상이 자신의 정보가 변경되거나 또는 이벤트가 발생할때
자신의 변경된 정보나 이벤트에 따른 어떠한 처리를 할 수 있도록 제공하는 함수라고 할 수 있습니다.

일단 우리 생활에서 예를 들자면

첫번째 상황.
철수와 영희가 놀이터에서 놀고있습니다. 철수는 엄마가 오후1시까지 집에 들어오라는 말을 듣고
시계에게 몇시인지 수시로 물어보다가 1시가되자 집으로 돌아갔습니다.

두번째 상황.
철수와 영희가 놀이터에서 놀고있습니다. 철수는 엄마가 오후1시까지 집에 들어오라는 말을 듣고
시계에게 후1시가 되면 알려달라고 한후 시계가 1시임을 알려주자 집으로 돌아갔습니다.

일단 위에서는 시계를 사람처럼 표현했습니다.
실제로는
첫번째는 철수가 영희와 놀다가 수시로 시간을 확인한 것이고,
두번째는 오후1시로 알람을 맞추고 영희와 논것입니다.

마찬가지로 차가 고장나서 카센터에 수리를 맡기고 수시로 수리가 완료되었는지 카센터에 전화를 해서 물어보는것보다
카센터에 자신의 전화번호를 알려주고 수리가 완료되면 알려달라고 하는것이 카센터쪽이나 수리를 맡긴사람이나 양쪽모두에게 편할 것입니다.

위의 두 예처럼 어떤 정보를 원하는 쪽이 정보를 제공하는 쪽에게 반복적으로 정보를 요구(또는 확인)하는 방법보다
정보를 제공하는 쪽이 정보를 원하는 쪽에게 통보하는 것이 효율적일 것입니다.

이런 상황에서 사용하면 좋은 것이 callback함수라고 보시면 됩니다.

-------------------------------------------------------------------------------------------------------------

http://rosagigantea.tistory.com/355

설명 #

"함수포인터"는 C언어에서 자주 쓰이는 기본 용법중 하나입니다. 정의는 다음과 같습니다.
선언된 함수가 저장된 메모리 번지값을 담고 있는 포인터 변수
하지만 이것을 왜 보통의 포인터와는 달리 특별취급하냐면 다음과 같은 이유 때문입니다.
  1. 일반 포인터 변수와는 조금 다르게 보이는 문법으로 선언됩니다. 예를 들어 함수 포인터 변수는 다음과 같이 선언합니다. (functionPtr이 포인터 변수명이 됩니다)
    void (*functionPtr)(const char *s_)
    
  2. 함수포인터는 실행부분을 가리키는 포인터 변수인탓에 () 연산자를 사용할 수 있습니다. 즉, 위의 functionPtr은 아래와 같이 실행가능합니다.
    functionPtr("바보나라~")
    

주로 함수포인터는 콜백(callback)을 구현하는데 사용됩니다. 어떤 라이브러리를 제작할 때 개발자가 어떤 "경우"에 대한 반응을 함수로 작성하고 이를 다시 라이브러리에서 호출하도록 작성하고자 할 때, 개발자가 작성한 함수의 포인터를 넘겨받아 실행하도록 하면 아주 유용할 때가 많습니다. (대표적인 예가 win32 api에서 윈도우 프로시져를 WNDCLASS의 lpfnWndProc맴버에 등록하는 부분을 들 수 있습니다) 즉, 함수를 마치 변수와 같이 취급하는 것이 가능해집니다.


예제 #

아래 예제는 함수포인터를 활용한 간단한 예제입니다.
#include <stdio.h>

void testout1(const char *s) {
printf("시험출력1:%s\n", s);
}

void testout2(const char *s) {
printf("시험출력2:%s\n", s);
}

// 함수포인터 변수
void (*funcPtr)(const char *s);

int main() {
// 함수포인터를 testout1, testout2로 각각 대입해보고 실행해본다.
funcPtr = testout1;
funcPtr("테스트");
funcPtr = testout2;
funcPtr("테스트");
}

실행결과는 아래와 같습니다.
시험출력1:테스트 시험출력2:테스트
main()안에서는 funcPtr만 실행했지만 마치 testout1, testout2를 각각 실행한 것과 같은 효과가 있음을 
알 수 있습니다.


typedef 거는 법 #

함수포인터를 어떤 포인터 변수로서 활용하고 싶을 때 typedef를 활용하면 매우 편리합니다. 실제로 win32 API에서는 윈도우 프로시저 함수포인터형으로 WNDPROC라는 타입이 있습니다. (이부분을 보면 어느정도 사용법에 대한 느낌이 올겁니다) winuser.h 헤더화일에서 검색해보면 다음과 같이 선언되어있습니다.
typedef LRESULT(CALLBACK *WNDPROC)(HWND,UINT,WPARAM,LPARAM);
실제로 사용될 때에는 다음과 같이 사용됩니다.
LRESULT CALLBACK winproc1(HWND,UINT,WPARAM,LPARAM) { }; ... WNDPROC winprocPtr = winproc1; ...
꽤 유용한 문법이니 알아두시면 좋습니다.

주의사항 #

함수포인터는 알아두면 상당히 유용한 기법이지만 사용시에는 다음과 같은 부분을 주의해야합니다.
  1. 대입되지 않은 (NULL값상태의) 함수포인터를 실행하지 않도록 주의해야합니다. 초기화를 항상 NULL로 해두고 실행전에 검사하는 것도 좋은 방법입니다.
  2. "같은 함수 포인터 타입"이라는 것을 증명하려면, 반환값, 매개변수의 타입 및 개수가 모두 일치해야합니다. 보통 하나라도 다른 함수포인터값을 대입하면 컴파일시 오류가 나게 됩니다.


출처 : http://www.redwiki.net/wiki/wiki.php/%C7%D4%BC%F6%C6%F7%C0%CE%C5%CD