#ifndef PTX_PLUGINS_H_INCLUDED #define PTX_PLUGINS_H_INCLUDED #include #include "macros.h" typedef struct ptx__plugin_manager_tag ptx_plugin_manager_t; typedef struct ptx__plugin_handle_tag ptx_plugin_t; /* returns: * - < 0 for plugin loading error (plugin will be unloaded) * - 0 for successful plugin startup * - (don't return values greater than 0 at this time) * usage: * Function will be called with this plugin instance and the "resume" pointer. * * The "resume" pointer will be NULL if the plugin is not being resumed. For this reason, it is not advised * to use NULL as a flag value in the restart function itself. */ typedef int (ptx_plugin_init_proc_t)(ptx_plugin_t * /*plugin*/, void * /*resume*/); enum { /* This plugin cannot be resumed at this time. The plugin manager will not unload it if it expects a "seamless" reload. * The plugin is expected to act as if this function was not called. */ DEINIT_ERR_RESUME_UNSUPPORTED = -1, /* The plugin supports being resumed, but due to a transient error condition (malloc failure?) the plugin could not set itself up for * resuming. If a plugin returns this value to the plugin manager, it is expected to act as if the function was not called. */ DEINIT_ERR_RESUME_FAILURE = -2, /* The plugin supports being resumed, but due to a transient error condition, the plugin could not set itself up for resuming. * Additionally, as a part of preparing to be reloaded, the plugin performed operations it could not roll back. Likely, an error * will be reported to the user, and the plugin will be unloaded. The plugin manager makes no assumptions about the behavior of the * plugin at this time. */ DEINIT_ERR_RESUME_UNRECOVERABLE = -3, /* The plugin is ready to be resumed/unloaded. */ DEINIT_OK = 0 }; /* returns: * - one of the values in the above enum. if the return value is anything else, the plugin manager's behavior is not defined. */ typedef int (ptx_plugin_deinit_proc_t)(ptx_plugin_t * /*plugin*/, void ** /*presume*/); #define PTX_CUR_PLUGIN_VERSION (1u) /* the fields of this struct are public. ABI changes should be marked by incrementing PTX_CUR_PLUGIN_VERSION */ struct ptx_plugin_desc { size_t desc_len; unsigned desc_ver; unsigned reserved; ptx_plugin_init_proc_t *init_proc; ptx_plugin_deinit_proc_t *deinit_proc; const char *name; const char *description; const char *version; }; /* for testing */ #ifdef _CLANGD #undef PTX_PLUGIN #define PTX_PLUGIN 1 #endif #define PTX__INTERNAL_PLUGIN_DESC_SYM ptx__plugin_spec #ifdef PTX_PLUGIN #define PTX_PLUGIN_DESC_START PTX_EXPORT \ const struct ptx_plugin_desc PTX__INTERNAL_PLUGIN_DESC_SYM = { \ .desc_len = sizeof(struct ptx_plugin_desc), \ .desc_ver = PTX_CUR_PLUGIN_VERSION, #define PTX_PLUGIN_NAME(_x) .name = _x, #define PTX_PLUGIN_DESCRIPTION(_x) .description = _x, #define PTX_PLUGIN_VERSION(_x) .version = _x, #define PTX_PLUGIN_INIT(_x) .init_proc = _x, #define PTX_PLUGIN_RESTART(_x) .restart_proc = _x, #define PTX_PLUGIN_DESC_END }; #endif PTX_INTERNAL(ptx_plugin_manager_t *ptx_plugin_manager_new(void) ATTR_MALLOC() ATTR_MALLOC((ptx_plugin_manager_free, 1)) ATTR_WUR); PTX_INTERNAL(void ptx_plugin_manager_free(ptx_plugin_manager_t *mgr)); PTX_INTERNAL(int ptx_plugin_manager_load_dir(ptx_plugin_manager_t *mgr, const char *dir)); /* initializes plugins which have not yet been initialized. returns the number of plugins which have been initialized and are still loaded * (plugins can return a failure from their initialization function, at which point the plugin will be unloaded.) */ PTX_INTERNAL(int ptx_plugin_manager_init_plugins(ptx_plugin_manager_t *mgr)); PTX_API void ptx_plugin_set_mainloop_func(ptx_plugin_t *plugin, void *func); #endif