Hook example code
Jump to navigation
Jump to search
#include "lldarray.h" // data1 and data2 may be used for any arbitrary user data. // from_plugin should be set to FALSE if the function is being called due to a user's action, // and TRUE if it is being called from another plugin. (The idea is to avoid event loops, but // maybe there is a better way. // If function pointer returns FALSE, and this is one of a series of callbacks for a hook, // the function should terminate without passing control to any further plugins or to the // rest of the viewer function. (This is to allow hook functions to "swallow" events by return FALSE.) typedef bool (*func_ptr)(void *data1, void *data2); class hook { public: const char * name; LLDynamicArray<func_ptr> *hook_ptrs; hook() {} hook(const char *n) {name = n; hook_ptrs = new (LLDynamicArray<func_ptr>)();} }; class viewer_func { public: const char * name; func_ptr ptr; viewer_func() {} viewer_func(const char * n, func_ptr p) { name=n; ptr=p;} }; class plugin_interface { private: hook * get_hook_by_name(const char *name); viewer_func * get_viewer_func_by_name(const char *name); public: LLDynamicArray<hook> hooks; LLDynamicArray<viewer_func> viewer_funcs; void add_hook(const char *name, const func_ptr ptr); void add_viewer_func(const char *name, func_ptr ptr); char ** get_viewer_func_list(); char ** get_hook_list(); const char * get_interface_version(); void * call_viewer_func(const char *name, void *data1, void *data2); bool call_hooks(const char *name, void *data1, void *data2); void init(); //plugin_interface(); }; #define PLUGIN_HOOK(name, data1, data2) fprintf(stderr, "PLUGIN_HOOK(%s)\n", name); if(!gPluginInterface.call_hooks(name, (void *)(data1), (void *)(data2))) return; extern plugin_interface gPluginInterface;
void plugin_interface::add_hook(const char *name, const func_ptr ptr) { /* This function adds a named hook definition with nothing to call to the list. It should be called once for each hooked function upon instantiation of the plugin interface; the hook_ptrs lists will be filled in, if necessary, by plugin init functions. We need a list of hook names (function names) so that plugins can ask the interface what hooks it will export. */ fprintf(stderr, "add_hook(%s = %p)\n", name, ptr); if(ptr) { hook * myhook = get_hook_by_name(name); if (myhook == NULL) { fprintf(stderr, "ERROR: tried to add function to unknown hook %s\n", name); return; } myhook->hook_ptrs->put(ptr); } else hooks.put(*(new hook(name))); }
hook * plugin_interface::get_hook_by_name(const char *name) { // this should really be a hash table lookup for(int i=0; i < hooks.count() ; i++) if (!strcasecmp(name, hooks[i].name)) return &hooks[i]; return NULL; }
bool plugin_interface::call_hooks(const char *name, void *data1, void *data2) { hook * func = get_hook_by_name(name); if (func) { for (int i=0; i < func->hook_ptrs->count(); i++) { LLDynamicArray<func_ptr> *fptr_array=func->hook_ptrs; func_ptr fptr=(*fptr_array)[i]; if (!(fptr)(data1, data2)) return FALSE; } return TRUE; } else return FALSE; }