MFC_C++ CallBack
2026. 3. 27. 14:20

 

 

 

 

 

 

 

 

 

 

 

🌟 CallBack 함수란?

더보기

"특정 상황이 되면 이 함수를 호출해줘" 라며 미리 등록해주는 함수

음식점에서 진동벨을 받고 자리에 앉아있는 것과 같다.

음식이 준비되면 → 진동벨이 울린다. (콜백 함수 호출)

손님은 카운터를 계속 바라볼 필요 없이 다른 일을 할 수 있다.

 

1단계 - 콜백 함수 타입 정의

typedef void (*pfLight_Status)(int nIndex, int nStatus);
//            ↑ 함수 포인터 타입 이름
//                              ↑ 이 형태의 함수를 가리킬 수 있음

 

2단계 - 콜백 함수를 등록하는 함수

void SetCallBack_Status(void* _ctx, pfLight_Status _pfStatus);
//                      ↑ 어느 객체에서 호출할지   ↑ 어떤 함수를 호출할지

 

3단계 - 실제 콜백 함수 (호출할 함수)

void CCameraLightDlg::CallBackAlarm(int nIndex, int nStatus)
{
    if (nStatus == 0)   AfxMessageBox(_T("연결되었습니다^^"));
    else                AfxMessageBox(_T("연결 실패...ㅠㅠ"));
}

 

4단계 - 콜백 등록

m_pEthernet->SetCallBack_Status(this, CallBackAlarm);
//                               ↑        ↑
//                          이 다이얼로그  호출할 함수
```

---

## 전체 흐름 정리
```
버튼 클릭
   ↓
BtnClickLightConnect() 실행
   ↓
SetCallBack_Status(this, CallBackAlarm) 등록
   ↓
ConnectTCP() 실행 (연결 시도 중...)
   ↓
연결 성공/실패 결과 나옴
   ↓
내부에서 등록된 CallBackAlarm(0, 결과값) 자동 호출
   ↓
"연결되었습니다^^" or "연결 실패...ㅠㅠ" 메시지 출력

 

콜백을 쓰는 이유는?

// 콜백 없는 방식 - 결과가 나올 때까지 무한 대기
while(연결중) {
    // 프로그램이 멈춰버림
}

// 콜백을 쓰면
// 콜백 방식 - 연결 시도하고 다른 작업 가능
ConnectTCP();  // 연결 시도만 하고
// → 결과가 나오면 알아서 CallBackAlarm이 불림
// → 그동안 프로그램은 다른 작업 가능

 

즉, 프로그램이 멈추지 않고 결과를 받을 수 있어서 사용함.

 

 

🌟 내가 이해한 CallBack 함수 (대리님이 만들어주신 예제 코드를 보며 정리)

더보기

콜백 함수가 무엇인가?

콜백 함수를 한 문장으로 표현하면 이렇다.
"지금 당장 실행하는 게 아니라, 나중에 특정 조건이 되면 불러줘!" 라고 미리 등록해두는 함수

예를 들어, 친구에게 이렇게 말하는 상황이다.
"나 밥 다 되면 불러줘. 그때 내가 직접 가져갈게."

여기서 "내가 직접 가져갈게."에 해당하는 행동이 바로 콜백 함수다.
밥이 다 된 시점(=조건 충족)에 친구(=다른 클래스/함수)가 나 대신 내 행동을 실행시켜주는 거다.

예제 코드 구조 한 눈에 보기

클래스 역할
CFuncTestDlg 버튼을 누르고, 결과를 화면에 표시하는 다이얼로그
CCalcTest 실제 계산 (합계/곱셈/뺄셈)을 수행하는 클래스

핵심은 CCalTest가 계산을 끝낸 뒤 결과를 어떻게 처리할지 직접 알 필요가 없다는 점이다. 그냥 콜백 함수를 불러주기만 하면 되니까!


단계별 코드 흐름 해설

step 1 ㅡ 콜백 함수 타입을 미리 정의한다

typedef void (*ComFunc)(void *ctx, int Res);

 

ComFunc 라는 이름으로 함수 포인터 타입을 만들어 둔 거다.

Void* 를 인자로 받는 이유는 어떤 객체든 받을 수 있게 하기 위해. (나중에 다이얼로그 주소를 여기에 담아 넘겨줌.)


step 2 ㅡ 콜백 함수를 미리 만들어 둔다.

// 선언 (헤더파일)
static void Excute(void* ctx, int Res);

// 구현 (cpp 파일)
void CFuncTestDlg::Excute(void* ctx, int Res)
{
	CFuncTestDlg* dlg = (CFuncTestDlg*)ctx;
    dlg->SetDlgItemInt(IDC_STATIC_1, Res);
}

 

Excute 함수가 바로 콜백 함수.

ctx로 받은 void*를 CFuncTestDlg*로 변환해서 다이얼로그의 함수를 호출.

"왜 static으로 선언했을까?"
일반 멤버 함수는 숨겨진 this 포인터가 붙어 있어서 함수 포인터로 넘기기가 까다롭다.
static 함수는 그런 제약이 없어서 주소를 깔끔하게 넘길 수 있다.

step 3 ㅡ 버튼을 누르면 콜백 함수를 등록하면서 요청한다.

void CFuncTestDlg::OnBnClickedButton1()
{
    c1.SettingCalc(this, 0, m_nArr, Excute);
    //             ^^^^  ^  ^^^^^^  ^^^^^^
    //           ctx   타입  배열  콜백함수 주소
}

 

버튼1을 누르면 SettingCalc를 호출한다.

4번째 인자로 Excute의 함수 주소를 넘겨주고 있다.

CCalcTest 입장에서는 "계산 끝나면 이 주소에 있는 함수 불러!" 라는 명령을 받은 셈.


step 4 ㅡ CCalcTest 내부에서 계산 후 콜백을 실행한다

void SettingCalc(void* ctx, int nType, int(&narr)[4], ComFunc Func)
{
    m_ctx  = ctx;
    m_Func = Func;  // 콜백 함수 주소를 저장!

    int nRes = 0;
    switch (m_nType) {
        case 0: nRes = TotalSum(narr); break;
        case 1: nRes = TotalMul(narr); break;
        case 2: nRes = TotalSub(narr); break;
    }

    m_Func(m_ctx, nRes);  // 저장해뒀던 콜백 함수 실행!
}

 

계산이 끝나고 나서 m_Func(m_ctx, nRes)로 콜백을 직접 호출.

이때 Excute 함수가 실행되고, 결과가 화면에 표시된다.


버튼별 실행 결과

배열 값은 {4, 7, 8, 9} 로 고정되어 있다.

버튼 nType 연산 함수 계산식 결과
Button1 0 TotalSum 4 + 7 + 8 + 9 28
Button2 1 TotalMul 4 x 7 x 8 x 9 2016
Button3 2 TotalSub 0 - 4 - 7 - 8 - 9 -28

핵심 포인트 정리

질문 답변
콜백 함수란? 내가 직접 호출한 게 아니라, 다른 쪽에서 조건이 충족되면 대신 불러주는 함수
왜 쓰나? CCalcTest가 결과 처리 방법 몰라도 됨. 콜백만 바꾸면 화면 출력, 파일 저장 등 자유롭게 교체 가능
void* ctx가 왜 필요한가? 콜백 내부에서 다이얼로그 객체의 함수를 호출해야 하기 때문에, 객체 주소를 담아 함께 넘겨주는 용도
static은 왜 붙이나? 멤버함수는 this 포인터 때문에 함수 포인터로 넘기기 어려움. static이면 깔끔하게 넘기기 가능

마치며

콜백 함수는 처음 보면 흐름이 왔다 갔다해서 헷갈리기 쉽다.
하지만 핵심은 하나,

"함수의 주소를 미리 넘겨두고, 나중에 불러달라고 예약하는 것."

이번 예제처럼 계산 클래스(CCalcTest)가 결과 처리 방식(Excute)을 직접 알 필요 없이, 
콜백만 교체하면 동작을 바꿀 수 있다는 게 콜백 함수의 가장 큰 장점.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'MFC_C++ > Task' 카테고리의 다른 글

MFC_C++ 스레드 (Thread)  (0) 2026.04.20
MFC_C++ 멀티바이트 vs 유니코드  (0) 2026.04.03
MFC_C++ 윈도우 계산기 리펙토링  (0) 2026.03.19
MFC_C++ 배열  (0) 2026.03.03