|
| #define | SPA_CALLBACK_VERSION_MIN(c, v) |
| | Check if a callback c is of at least version v.
|
| #define | SPA_CALLBACK_CHECK(c, m, v) |
| | Check if a callback c has method m of version v.
|
| #define | SPA_CALLBACKS_INIT(_funcs, _data) |
| | Initialize the set of functions funcs as a spa_callbacks, together with _data.
|
| #define | SPA_INTERFACE_INIT(_type, _version, _funcs, _data) |
| | Initialize a spa_interface.
|
| #define | spa_callbacks_call(callbacks, type, method, vers, ...) |
| | Invoke method named method in the callbacks.
|
| #define | spa_callbacks_call_fast(callbacks, type, method, vers, ...) |
| #define | spa_callback_version_min(callbacks, type, vers) |
| | True if the callbacks are of version vers, false otherwise.
|
| #define | spa_callback_check(callbacks, type, method, vers) |
| | True if the callbacks contains method of version vers, false otherwise.
|
| #define | spa_callbacks_call_res(callbacks, type, res, method, vers, ...) |
| | Invoke method named method in the callbacks.
|
| #define | spa_callbacks_call_fast_res(callbacks, type, res, method, vers, ...) |
| #define | spa_interface_callback_version_min(iface, method_type, vers) |
| | True if the iface's callbacks are of version vers, false otherwise.
|
| #define | spa_interface_callback_check(iface, method_type, method, vers) |
| | True if the iface's callback method is of version vers and exists, false otherwise.
|
| #define | spa_interface_call(iface, method_type, method, vers, ...) |
| | Invoke method named method in the callbacks on the given interface object.
|
| #define | spa_interface_call_fast(iface, method_type, method, vers, ...) |
| #define | spa_interface_call_res(iface, method_type, res, method, vers, ...) |
| | Invoke method named method in the callbacks on the given interface object.
|
| #define | spa_interface_call_fast_res(iface, method_type, res, method, vers, ...) |
| #define | spa_api_func_v(o, method, version, ...) |
| #define | spa_api_func_r(rtype, def, o, method, version, ...) |
| #define | spa_api_func_fast(o, method, ...) |
| #define | spa_api_method_v(type, o, method, version, ...) |
| #define | spa_api_method_r(rtype, def, type, o, method, version, ...) |
| #define | spa_api_method_null_v(type, co, o, method, version, ...) |
| #define | spa_api_method_null_r(rtype, def, type, co, o, method, version, ...) |
| #define | spa_api_method_fast_v(type, o, method, version, ...) |
| #define | spa_api_method_fast_r(rtype, def, type, o, method, version, ...) |
Generic implementation of implementation-independent interfaces.
A SPA Interface is a generic struct that, together with a few macros, provides a generic way of invoking methods on objects without knowing the details of the implementation.
The primary interaction with interfaces is through macros that expand into the right method call. For the implementation of an interface, we need two structs and a macro to invoke the bar method:
struct foo_methods {
uint32_t version;
void (*bar)(void *object, const char *msg);
};
struct foo {
int some_other_field;
...
};
#define foo_bar(obj, ...) ({ \
struct foo *f = obj;
struct foo_methods,
bar,
0,
__VA_ARGS__
);/
})
#define spa_interface_call(iface, method_type, method, vers,...)
Invoke method named method in the callbacks on the given interface object.
Definition hook.h:248
The struct foo_methods and the invocation macro foo_bar() must be available to the caller. The implementation of struct foo can be private.
void main(void) {
struct foo *myfoo = get_foo_from_somewhere();
foo_bar(myfoo, "Invoking bar() on myfoo");
}
The expansion of foo_bar() resolves roughly into this code:
void main(void) {
struct foo *myfoo = get_foo_from_somewhere();
if (0 >= methods->version &&
methods->bar)
methods->bar(myfoo, "Invoking bar() on myfoo");
}
struct spa_callbacks cb
Definition hook.h:151
The typecast used in foo_bar() allows struct foo to be opaque to the caller. The implementation may assign the callback methods at object instantiation, and the caller will transparently invoke the method on the given object. For example, the following code assigns a different bar() method on Mondays - the caller does not need to know this.
static void bar_stdout(struct foo *f, const char *msg) {
printf(msg);
}
static void bar_stderr(struct foo *f, const char *msg) {
fprintf(stderr, msg);
}
struct foo* get_foo_from_somewhere() {
struct foo *f = calloc(sizeof struct foo);
f->iface->cb = (struct foo_methods*) { .bar = bar_stdout };
if (today_is_monday)
f->iface->cb = (struct foo_methods*) { .bar = bar_stderr };
return f;
}