You can do the same thing as the article you linked. To wrap malloc:
// wrap.h
#define malloc(N) wrapped_malloc(N)
void *wrapped_malloc(size_t n);
// wrap.c
#include "wrap.h"
#undef malloc
void *wrapped_malloc(size_t n) {
printf("called malloc\n");
return malloc(n);
}
// mycode.c
#include "wrap.h"
...
void *p = malloc(42);
...
Prints "called malloc" when it executes.
Or maybe I'm misunderstanding your question. If so, give an example.
Addition
Contrary to your use of terms, there is no inherent connection between callbacks and asynchronous execution. For example, libpng makes excellent use of callbacks.
But since you are probably interested in thread management calls, let's wrap:
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void*), void *arg);
For this we define:
// wrap.h
#define pthread_create(Thread, Attr, StartRoutine, Arg) \
wrapped_pthread_create(Thread, Attr, StartRoutine, Arg)
int wrapped_pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void*), void *arg);
Then:
// wrap.c
#include "wrap.h"
#undef pthread_create
// __thread is gcc's thread local storage class keyword.
// If you're using a different compiler, adjust accordingly.
static __thread void *(*captured_start_routine)(void*);
static void *wrapped_start_routine(void *arg) {
printf("called start routine\n");
return captured_start_routine(arg);
}
int wrapped_pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void*), void *arg) {
captured_start_routine = start_routine;
printf("called pthread_create\n");
return pthread_create(thread, attr, wrapped_start_routine, arg);
}