/** \defgroup spa_interfaces Interfaces * *\briefGenericimplementationofimplementation-independentinterfaces * *ASPAInterfaceisagenericstructthat,togetherwithafewmacros, *providesagenericwayofinvokingmethodsonobjectswithoutknowingthe *detailsoftheimplementation. * *Theprimaryinteractionwithinterfacesisthroughmacrosthatexpandinto *therightmethodcall.Fortheimplementationofaninterface,weneedtwo *structsandamacrotoinvokethe`bar`method: * *\code{.c} *// this struct must be public and defines the interface to a *// struct foo *structfoo_methods{ *uint32_tversion; *void(*bar)(void*object,constchar*msg); *}; * *// this struct does not need to be public *structfoo{ *structspa_interfaceiface;// must be first element, see foo_bar() *intsome_other_field; *... *}; * *// if struct foo is private, we need to cast to a *// generic spa_interface object *#definefoo_bar(obj,...)({\ *structfoo*f=obj; *spa_interface_call((structspa_interface*)f,// pointer to spa_interface in foo *structfoo_methods,// type of callbacks *bar,// name of methods *0,// hardcoded version to match foo_methods->version *__VA_ARGS__// pass rest of args through *);/ *}) *\endcode * *The`structfoo_methods`andtheinvocationmacro`foo_bar()`mustbe *availabletothecaller.Theimplementationof`structfoo`canbeprivate. * *\code{.c} *voidmain(void){ *structfoo*myfoo=get_foo_from_somewhere(); *foo_bar(myfoo,"Invokingbar()onmyfoo"); *} *\endcode *Theexpansionof`foo_bar()`resolvesroughlyintothiscode: *\code{.c} *voidmain(void){ *structfoo*myfoo=get_foo_from_somewhere(); *// foo_bar(myfoo, "Invoking bar() on myfoo"); *conststructfoo_methods*methods=((structspa_interface*)myfoo)->cb; *if(0>=methods->version&&// version check *methods->bar)// compile error if this function does not exist, *methods->bar(myfoo,"Invokingbar()onmyfoo"); *} *\endcode * *Thetypecastusedin`foo_bar()`allows`structfoo`tobeopaquetothe *caller.Theimplementationmayassignthecallbackmethodsatobject *instantiation,andthecallerwilltransparentlyinvokethemethodonthe *givenobject.Forexample,thefollowingcodeassignsadifferent`bar()`methodon *Mondays-thecallerdoesnotneedtoknowthis. *\code{.c} * *staticvoidbar_stdout(structfoo*f,constchar*msg){ *printf(msg); *} *staticvoidbar_stderr(structfoo*f,constchar*msg){ *fprintf(stderr,msg); *} * *structfoo*get_foo_from_somewhere(){ *structfoo*f=calloc(sizeofstructfoo); *// illustrative only, use SPA_INTERFACE_INIT() *f->iface->cb=(structfoo_methods*){.bar=bar_stdout}; *if(today_is_monday) *f->iface->cb=(structfoo_methods*){.bar=bar_stderr}; *returnf; *} *\endcode
*/
/** \defgroup spa_hooks Hooks * *ASPAHookisadatastructuretokeeptrackofcallbacks.Itissimilarto *the\refspa_interfacesandtypicallyusedwhereanimplementationallows *formultipleexternalcallbackfunctions.Forexample,animplementationmay *useahooklisttoimplementsignalswitheachcallerusingahookto *registercallbackstobeinvokedonthosesignals. * *Thebelow(pseudo)codeisaminimalexampleoutliningtheuseofhooks: *\code{.c} *// the public interface *#defineVERSION_BAR_EVENTS0// version of the vtable *structbar_events{ *uint32_tversion;// NOTE: an integral member named `version` *// must be present in the vtable *void(*boom)(void*data,constchar*msg); *}; * *// private implementation *structparty{ *structspa_hook_listbar_list; *}; * *voidparty_add_event_listener(structparty*p,structspa_hook*listener, *conststructbar_events*events,void*data) *{ *spa_hook_list_append(&p->bar_list,listener,events,data); *} * *staticvoidparty_on(structparty*p) *{ *// NOTE: this is a macro, it evaluates to an integer, *// which is the number of hooks called *spa_hook_list_call(&p->list, *structbar_events,// vtable type *boom,// function name *0,// hardcoded version, *// usually the version in which `boom` *// has been added to the vtable *"partyon,wayne"// function argument(s) *); *} *\endcode * *Inthecaller,thehookscanbeusedlikethis: *\code{.c} *staticvoidboom_cb(void*data,constchar*msg){ *// data is userdata from main() *printf("%s",msg); *} * *staticconststructbar_eventsevents={ *.version=VERSION_BAR_EVENTS,// version of the implemented interface *.boom=boom_cb, *}; * *voidmain(void){ *void*userdata=whatever; *structspa_hookhook; *structparty*p=start_the_party(); * *party_add_event_listener(p,&hook,&events,userdata); * *mainloop(); *return0; *} * *\endcode
*/
/** *\addtogroupspa_hooks *\{
*/
/** \struct spa_hook_list *Alistofhooks.Thisstructisprimarilyusedby
* implementation that use multiple caller-provided \ref spa_hook. */ struct spa_hook_list { struct spa_list list;
};
/** \struct spa_hook *Ahook,containsthestructurewithfunctionsandthedatapassed *tothefunctions. * *Ahookshouldbetreatedasopaquebythecaller.
*/ struct spa_hook { struct spa_list link; struct spa_callbacks cb; /** callback and data for the hook list, private to the
* hook_list implementor */ void (*removed) (struct spa_hook *hook); void *priv;
};
/** Initialize a hook list to the empty list*/
SPA_API_HOOK void spa_hook_list_init(struct spa_hook_list *list)
{
spa_list_init(&list->list);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.