4 Many [objects](@ref md_doc_util_object) in the Lely libraries allow the user to
5 register callback functions. The function signature and registration method all
6 follow the pattern shown here.
8 Example of a public C header (lely/lib/obj.h):
11 // Ensure that callback functions also use the C calling convention.
15 // The last argument of a callback function is always a pointer to
16 // user-specified data.
17 typedef void callback_func_t(Args... args, void *data);
19 // Retrieves a pointer to the callback function and the user-specified data.
20 void obj_get_func(const obj_t *obj, callback_func_t **pfunc, void **pdata);
22 // Sets a callback function. The data pointer is passed as the last argument in
23 // each invocation of func.
24 void obj_set_func(obj_t *obj, callback_func_t *func, void *data);
31 Example of the C implementation (obj.c):
35 callback_func_t *callback_func;
40 // An internal helper function that invokes the callback if it is set.
41 static void obj_callback(obj_t *obj, Args... args);
44 __obj_init(struct __obj *obj, Args... args)
48 obj->callback_func = NULL;
49 obj->callback_data = NULL;
55 obj_get_func(const obj_t *obj, callback_func_t **pfunc, void **pdata)
60 *pfunc = obj->callback_func;
62 *pdata = obj->callback_data;
66 obj_set_func(obj_t *obj, callback_func_t *func, void *data)
70 obj->callback_func = func;
71 obj->callback_data = data;
75 obj_callback(obj_t *obj, Args... args)
79 if (obj->callback_func)
80 obj->callback_func(args..., obj->callback_data);
84 The user-specified data pointer can be used to allow the registration of C++
85 function objects or member functions. lely/util/c_call.hpp provides several
86 templates to automatically generate the required wrapper functions.
88 Example of a public C++ header (lely/lib/obj.hpp):
90 // Include the c_obj_call<>, c_mem_call<> and c_mem_fn<> templates.
91 #include <lely/util/c_call.hpp>
100 getFunc(callback_func_t** pfunc, void** pdata) const noexcept
102 obj_get_func(this, pfunc, pdata);
105 // Registers a C-style callback function. The user specifies the data
108 setFunc(callback_func_t* func, void* data) noexcept
110 obj_set_func(this, func, data);
113 // Registers a function object as the callback. The data pointer is used
114 // to store the address of the function object and is therefore not
115 // available to the user.
118 setFunc(F* f) noexcept
120 setFunc(&c_obj_call<callback_func_t*, F>::function,
121 static_cast<void*>(f));
124 // Registers a member function as the callback. The first template
125 // parameter is the class containing the member function, the second is
126 // the address of the member function. The data pointer is used to store
127 // the address of the class instance and is therefore not available to
129 template <class C, typename c_mem_fn<callback_func_t*, C>::type M>
131 setFunc(C* obj) noexcept
133 setFunc(&c_mem_call<callback_func_t*, C, M>::function,
134 static_cast<void*>(obj));
143 Registering a C-style global (or static) function in C++ is similar to C:
145 void myFunc(Args... args, void* data) noexcept;
148 setFunc(Obj* obj, void* data)
150 obj->setFunc(&myFunc, data);
154 The second form of `setFunc()` allows registering a function object. The user is
155 responsible for lifetime of the object.
158 void operator()(Args... args) noexcept;
162 setFunc(Obj* obj, MyFuncObj* f)
168 The third form of `setFunc()` allows member functions to be registered as
169 callbacks. Again, the user is responsible for the lifetime of the instance of
170 the class containing the member function.
174 void myFunc(Args... args) noexcept;
178 setFunc(Obj* obj, MyClass* cls)
180 obj->setFunc<MyClass, &MyClass::myFunc>(cls);
183 It is also possible to register private methods as callbacks, but only from a
184 function which has private access (i.e., a friend or another method).