dyncallback -- callback interface of dyncall
dcbNewCallback(const char * signature, DCCallbackHandler * funcptr,
void * userdata);
dcbInitCallback(DCCallback * pcb, const char * signature,
DCCallbackHandler * funcptr, void * userdata);
dcbFreeCallback(DCCallback * pcb);
dcbGetUserData(DCCallback * pcb);
The dyncallback dyncall library has an interface to create callback
objects, that can be passed to functions as callback arguments. In other
words, a pointer to the callback object can be "called", directly. The
callback handler then allows iterating dynamically over the arguments
once called back.
dcbNewCallback() creates a new callback object, where signature is a sig-
nature string describing the function to be called back (see manual or
dyncall_signature.h for format). This is needed for dyncallback dyncall-
back to correctly prepare the arguments passed in by the function that
calls the callback handler. Note that the handler doesn't return the
value specified in the signature, directly, but a signature character,
specifying the return value's type. The return value itself is stored
where the handler's 3rd parameter points to (see below). funcptr is a
pointer to the dyncallback dyncallback callback handler (see below), and
userdata a pointer to arbitrary user data you want to use in the callback
handler. Use the returned pointer as callback argument in functions
requiring a callback function pointer.
dcbInitCallback() (re)initialize the callback object.
dcbFreeCallback() destroys and frees the callback handler.
dcbGetUserData() returns a pointer to the userdata passed to the callback
object on creation or initialization.
Declaration of a dyncallback handler (following function pointer defini-
tion in dyncallback/dyncall_callback.h):
char cbHandler(DCCallback* cb,
cb is a pointer to the DCCallback object in use dyncallback result is a
pointer to a DCValue object in order to store the callback's return value
(output, to be set by handler). Finally, userdata is a pointer to some
user defined data that can be set when creating the callback object. The
handler itself returns a signature character (see manual for format)
specifying the data type used for result.
Let's say, we want to create a callback object and call it. For simplic-
ity, this example will omit passing it as a function pointer to a func-
tion (e.g. compar in qsort(), etc.) and demonstrate calling it, directly.
First, we need to define our callback handler - the following handler
illustrates how to access the passed- in arguments:
char cbHandler(DCCallback* cb,
int* ud = (int*)userdata;
int arg1 = dcbArgInt (args);
float arg2 = dcbArgFloat (args);
short arg3 = dcbArgShort (args);
double arg4 = dcbArgDouble (args);
long long arg5 = dcbArgLongLong(args);
// .. do something ..
result->s = 1244;
Note that the return value of the handler is a signature character, not
the actual return value, itself. Now, let's call it through a DCCallback
short result = 0;
int userdata = 1337;
cb = dcbNewCallback("ifsdl)s", &cbHandler, &userdata);
result = ((short(*)(int, float, short, double, long long))cb)
(123, 23.f, 3, 1.82, 9909ll);
The dyncallback library needs at least a c99 compiler with additional
support for anonymous structs/unions (which were introduced officially in
c11). Given that those are generally supported by pretty much all major
c99 conforming compilers (as default extension), it should build fine
with a c99 toolchain. Strictly speaking, dyncall conforms to c11,
dyncall(3), dynload(3) and the dyncall manual (available in HTML and PDF
format) for more information.
Daniel Adler <firstname.lastname@example.org>
Tassilo Philipp <email@example.com>
May 6, 2018