C – Callback Function

Callback function hay hàm callback trong lập trình C là gì?

Callback function là những hàm cực kỳ linh hoạt, đặc biệt là trong lập trình hướng sự kiện (event-driven programming). Khi một sự kiện cụ thể được kích hoạt (trigger), một hàm callback được ánh xạ tới sự kiện đó sẽ được thực thi để phản hồi các sự kiện này. Điều này thường được sử dụng trong các ứng dụng GUI, một hành động như click vào nút nhấn có thể khởi tạo một loạt các hành động được xác định trước.

Callback Function

Callback function cơ bản là những đoạn code thực thi được truyền dưới dạng đối số (argument) vào code khác. Nó được dự định sẽ gọi ngược về (call back) hoặc thực thi (execute) đối số tại một thời điểm nhất định. Chúng ta có thể định nghĩa nó theo cách khác là: “Nếu tham chiếu (reference) của một hàm được truyền (pass) cho đối số hàm khác để gọi, thì nó được gọi là hàm callback.”

Cơ chế của callback phụ thuộc vào con trỏ hàm (function pointer). Con trỏ hàm là biến lưu trữ địa chỉ bộ nhớ của hàm.

Dưới đây là hàm hello() đơn giản trong C.

void hello(){
   printf("Hello World.");
}

Khai báo một con trỏ hàm ptr và trỏ tới hàm này.

void (*ptr)() = &hello;

Bây giờ, chúng ta có thể gọi hàm thông qua con trỏ hàm này.

(*ptr)();  // or just call ptr();

Ví dụ Callback Function trong C

Trong ví dụ này, hàm hello() được định nghĩa là một đối số của callback().

void hello(){
   printf("Hello World\n");
}

void callback(void (*ptr)()){
   printf("Calling a function with its pointer\n");
   (*ptr)();   // calling the callback function
}

int main(){
   void (*ptr)() = hello;
   callback(ptr);
   return 0;
}

Kết quả:

Calling a function with its pointer
Hello World

Callback Function với đối số

Trong ví dụ tiếp theo, chúng ta khai báo hai hàm có prototype như sau. square()root().

int square(int val){
   return val*val;
}

int root(int val){
   return pow(val, 0.5);
}

Định nghĩa hàm callback nhận một đối số là một con trỏ hàm với một số nguyên tương (integer) ứng với hai hàm trên.

int callback(int a, int (*ptr)(int)){
   int ret = (*ptr)(a);
   return ret;
}

Trong hàm main(), chúng ta gọi hàm callback bằng cách truyền một số nguyên và tên của hàm (square hoặc root) để trở thành con trỏ hàm trong định nghĩa của callback.

Ví dụ Callback Function với đối số

Code hoàn chỉnh như dưới đây.

#include <stdio.h>
#include <math.h>

int callback(int a, int (*print_callback)(int));
int square(int value);
int root (int value);

int main(){
   
   int x = 4;
   
   printf("Square of x: %d is %d\n", x, callback(x, square));
   printf("Square root of x: %d is %d\n", x, callback(x, root));
   
   return 0;
}

int callback(int a,  int (*ptr)(int)){
   int ret = (*ptr)(a);
   return ret;
}

int square(int val){
   return val*val;
}

int root(int val){
   return pow(val, 0.5);
}

Kết quả

Square of x: 4 is 16
Square root of x: 4 is 2

Các kiểu Callbacks trong C

Có hai kiểu (type) callbacks là:

Callback Đồng Bộ (Synchronous Callback)

Một callback là đồng bộ (synchronous) khi nó được đưa cho một hàm khác, hàm này thực thi callback như một phần quy trình của hàm. Hàm gọi (calling function) chờ callback hoàn tất để tiếp tục. Điều này có ích khi bạn cần kết quả ngay lập tức hoặc muốn đảm bảo một tác vụ đã hoàn tất trước khi tiếp tục.

Callback Bất Đồng Bộ (Asynchronous Callback)

Trong trường hợp này, hàm gọi (calling function) trigger callback nhưng không đợi callback kết thúc. Thay vào đó, hàm tiếp tục thực thi. Việc này tạo ra các thao tác không bị chặn (non-blocking operation). Nó thường được sử dụng trong lập trình hướng sự kiện (event-driven programming).

Nhìn chung callback function giúp các nhà phát triển viết các chương trình C linh hoạt và thích ứng tốt hơn.

Chương này đã giải thích cách để bạn có thể sử dụng các con trỏ hàm để tăng cường tính linh hoạt của các chương trình C. Ngoài ra, mình đã chỉ ra cách để bạn có thể tạo các callback function tổng quát mà không bị giới hạn bởi kiểu con trỏ hàm (function pointer type) đặc trưng nào.

(Tiếp theo)

Icons made by Freepik from www.flaticon.com