diff options
Diffstat (limited to 'src/plugins/plugin_manager.c')
| -rw-r--r-- | src/plugins/plugin_manager.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/src/plugins/plugin_manager.c b/src/plugins/plugin_manager.c new file mode 100644 index 0000000..a135e06 --- /dev/null +++ b/src/plugins/plugin_manager.c @@ -0,0 +1,105 @@ + +#include "plugin_manager.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dlfcn.h> + +// Linked list node for plugins. +typedef struct PluginNode +{ + ZPlugin *plugin; + void *handle; // dlopen handle (NULL for built-ins). + struct PluginNode *next; +} PluginNode; + +static PluginNode *head = NULL; + +void zptr_plugin_mgr_init(void) +{ + head = NULL; +} + +void zptr_register_plugin(ZPlugin *plugin) +{ + if (!plugin) + { + return; + } + + if (zptr_find_plugin(plugin->name)) + { + return; + } + + PluginNode *node = malloc(sizeof(PluginNode)); + node->plugin = plugin; + node->handle = NULL; + node->next = head; + head = node; +} + +int zptr_load_plugin(const char *path) +{ + void *handle = dlopen(path, RTLD_LAZY); + if (!handle) + { + fprintf(stderr, "Failed to load plugin '%s': %s\n", path, dlerror()); + return 0; + } + + ZPluginInitFn init_fn = (ZPluginInitFn)dlsym(handle, "z_plugin_init"); + if (!init_fn) + { + fprintf(stderr, "Plugin '%s' missing 'z_plugin_init' symbol\n", path); + dlclose(handle); + return 0; + } + + ZPlugin *plugin = init_fn(); + if (!plugin) + { + fprintf(stderr, "Plugin '%s' init returned NULL\n", path); + dlclose(handle); + return 0; + } + + // Register + PluginNode *node = malloc(sizeof(PluginNode)); + node->plugin = plugin; + node->handle = handle; + node->next = head; + head = node; + + return 1; +} + +ZPlugin *zptr_find_plugin(const char *name) +{ + PluginNode *curr = head; + while (curr) + { + if (strcmp(curr->plugin->name, name) == 0) + { + return curr->plugin; + } + curr = curr->next; + } + return NULL; +} + +void zptr_plugin_mgr_cleanup(void) +{ + PluginNode *curr = head; + while (curr) + { + PluginNode *next = curr->next; + if (curr->handle) + { + dlclose(curr->handle); + } + free(curr); + curr = next; + } + head = NULL; +} |
