관리 메뉴

드럼치는 프로그래머

[C/C++] callback 함수의 이해 본문

★─Programing/☆─C | C++

[C/C++] callback 함수의 이해

드럼치는한동이 2011. 11. 1. 17:34
 

callback 함수는 아마 WinAPI 프로그래밍할 때 많이 보셨을겁니다.

 

callback이란 무엇일까요?

 

해석해보면 "불러-다시" 뭐 이렇게 되나요...ㅋ

 

찾아보니 정의는 이렇군요.


 

호출될 함수를 알려 주어 다른 프로그램 또는 다른 모듈에서 함수를 호출하게 하는 방법. 일반적으로 운영 체계(OS)가 호출할 애플리케이션의 함수를 지정해 특정한 사건 또는 메시지가 발생했을 때 호출되도록 지정할 수 있다. 이런 함수를 콜백 함수라고 한다.


그냥 함수 호출과 callback 함수 호출의 차이점은 "제어권"에 있습니다.

 

일반적으로 함수 호출은 조건 1이면 1번 함수를 불러서 처리, 2면 2번 함수 불러서 처리... 이런 식입니다.

 

즉, 우리가 어떤 처리가 필요할 때 함수에게 그 작업을 맡기는 것이죠.

 

그런데 callback 함수는 내가 필요할 때 호출해서 사용하는 것이 아니고,

 

어떤 이벤트가 발생 했을 때 나에게 알려달라고 하는 것입니다. 즉, 호출 되는 것이라고 봐야합니다.

 

이 개념을 그림으로 나타내면 다음과 같습니다.

 

 

fig1. 이벤트 발생 시 호출할 handler를 등록


fig2. 이벤트가 발생하여 handler를 호출

그래서 WinAPI에서는 handler를 등록한 후 이벤트가 떨어지면 handler가 호출 되고 그 안에서 필요한 처리를 하게 됩니다.

 

다음은 간단한 시뮬레이션 코드입니다.


#include <stdio.h>

#include <ctype.h>

#include <string.h>

 

typedef void (*callback_key)(int id, int ch);

 

int handlerNum = 0;

callback_key callArr[16];

 

void procKeyA(int id, int ch)

{

       if (isdigit(ch)) {

             printf("A: id(%d),input(%d)\n", id, ch);

       }

}

 

void procKeyB(int id, int ch)

{

       if (isdigit(ch)) {

             printf("B: id(%d),input(%d)\n", id, ch);

       } else if (isalpha(ch)) {

             printf("B: id(%d),input(%c)\n", id, ch);

       }

 

       for(int i=0; i<10; i++) {

             printf("do something...(%d)\n", i);

       }

}

 

void callReg(callback_key handler)

{           

       callArr[handlerNum] = handler;

       handlerNum++;

}

 

// user input for simulation

int userInput()

{

       static char in[] = "12abcd234alkfz1ff";

       static int cnt = 0;

       static int inIdx = 0;

       static int len = strlen(in);

       int ret = 0;

 

       if (cnt % 5 == 0) {

             if (cnt != 0) cnt=0;

             if (inIdx == len) {

                    ret = -1;

             } else {

                    ret = in[inIdx++];

             }

       }

       cnt++;

       return ret;

}

 

int main(int argc, char *argv[])

{

       int ch;

 

       callReg(procKeyA);

       callReg(procKeyB);

 

       while(1)

       {

             ch = userInput();

 

             if (ch != 0) {

                    // system end

                    if (ch == -1) break;

                    // call handler

                    for(int i=0; i<handlerNum; i++) {

                           callArr[i](i, ch);

                    }

             } else {

                    printf("normal state A, B\n");

             }

       }

       return 0;

}


userInput이라는 함수가 user라고 가정하고, 일정 시기마다 key입력을 발생 시키는 시나리오입니다.

 

procKeyA,B는 application이 등록한 handler 함수에 해당합니다.


Comments