[C] 라이브러리와 콜백 함수

김태희·2023년 11월 29일
0
post-thumbnail

콜백 함수

공부하는 책인 Do it! C언어 입문(김성엽)에서 콜백 함수를 쉽게 잘 풀어서 설명해주는 것 같아 일부를 인용하여 게시글을 작성한다.

C언어 공부를 통해 기초를 다지거나 더 자세히 보고싶다면 책을 사서 보길 추천한다.


라이브러리


라이브러리 프로그래머

완제품 형식의 프로그램을 만드는 프로그래머도 있는 반면에 음성 데이터를 압축하거나 영상 데이터를 변환하는 등 특별한 지식이 필요한 기능을 쉽게 사용할 수 있도록 함수로 만들어서 판매하는 프로그래머들도 있다.

이러한 프로그래머들을 라이브러리 프로그래머라고 한다.

이들은 자신의 코드가 노출되면 안 되기 때문에 코드를 컴파일해 라이브러리(library, *.lib) 형식의 파일로 제공하고, 라이브러리 안의 함수들이 어떤 형태로 선언된 함수인지 알아야 코드를 자세히 볼 수 없는 사용자들이 사용할 수 있기에 함수의 원형들을 헤더(header, *.h) 파일에 적어서 함께 제공한다.

예시를 들어 설명하자면, 두 정수의 합을 구하는 Sum 함수를 포함하는 라이브러리에서

사용자가 라이브러리 파일을 볼 수는 없겠지만 파일 안에는 아래와 같은 형식의 코드가 있을 것이다.

int Sum(int a, int b){
  return a+b;
}

헤더에는 아래처럼 함수의 원형 형태로 저장되어 있을 것이다.

int Sum(int a, int b);

그렇다면 사용자는 헤더를 참고하여 아래의 형태처럼 Sum 함수를 사용할 수 있을 것이다.

#include "sum.h"
#pragma comment(lib, "sum.lib")
void main(){
  int result = Sum(2, 3);
}

이런 식으로 라이브러리가 활용된다.


라이브러리 기능좀 추가해주세요..

여기서 만약 라이브러리의 사용자들이 Sum 함수에 전달되는 두 숫자 값이 음수일시에 양수로 변환해서 합산하는 함수도 추가로 만들어달라고 요청한다면, 라이브러리 프로그래머는 아래와 같이 새로운 기능이 추가된 Sum_absolute 함수를 라이브러리에 추가해야할 것이다.

int Sum(int a, int b){
  return a+b;
}
int Sum_absolute(int a, int b){
  if(a<0) a *= (-1); //절대값 구하기
  if(b<0) b *= (-1);
  return a+b;
}

여기서 이러한 불편함을 없애고자 사용자가 라이브러리의 코드를 보지 않으면서도 매개변수를 통해 함수에 기능을 추가할 수 있도록 라이브러리 프로그래머가 미리 설계한다.

int Sum(int a, int b, void (*pa)(int *), void (*pb)(int *)){
  if(NULL != pa) (*pa)(&a);
  if(NULL != pb) (*pb)(&b);
  return a+b;
}

그렇다면 헤더 파일은 아래와 같을 것이다.

int Sum(int a, int b, void(*pa)(int *), void (*pb)(int *));

이를 마주한 라이브러리 사용자는 아래와 같은 코드를 통해 이 라이브러리를 이용할 수 있을 것이다.

#include "sum.h"
#pragma comment(lib, "sum.lib")

void Absolute(int *p){
  if(*p<0) *p = (*p) * (-1)
}
void main(){
  int result = Sum(-2, 3, Absolute, NULL); //5
  int result = Sum(2, -3, Absolute, NULL); //-1
  int result = Sum(-2, -3, Absolute, Absolute); //5
}

여기서 Absolute()의 주소값이 포인터 변수 pa에 들어가면서 라이브러리에서 *paa의 주소값을 받아 실행되며 *pa가 뜻하는 Absolute(a)가 실행되게 되는 것이다.

이해가 안 간다면 이전 글에서 함수 포인터에 대해 공부하고 오길 바란다.


콜백과 콜백 함수

이처럼 자신이 사용할 함수가 명시적으로 호출되지않고 함수 포인터에 의해서 호출되는 방식을 '콜백'이라고 부른다.

그리고 호출되는 함수(Absolute())를 콜백 함수라고 부른다.



요약

이제 다 이해했다고 가정한 상태에서 쉽게 요약하자면 많은 사용자들의 다양한 조건을 미리 예측해 반영하면 좋겠지만, 조건문이 많아지는 비효율적인 함수가 되는것을 막기위해 함수 포인터를 사용하여 라이브러리 사용자들에게 조건이나 요구를 스스로 반영할 수 있도록 도움을 요청하는 것이다.

이 방식을 사용해 여러 문제나 나중에 추가될 기술과 같은 변화에 대비할 수 있고, 라이브러리가 노출되지 않고도 사용자에게 사용성을 높여줄 수 있다.

막상 이해하고 나면 크게 어려운 개념은 아니지만 이를 설명하는건 정말 어려운 것 같다.
어렵게 공부해온 포인터가 점점 많은 기능을 수행하는 걸 보니 C언어를 공부한 보람이 있는 것 같다.

0개의 댓글