Last active
January 1, 2016 11:19
-
-
Save mgdm/8137592 to your computer and use it in GitHub Desktop.
A simple and probably flawed base for a plugin system using DSOs in C.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <dlfcn.h> | |
| #include "plugin_api.h" | |
| plugin_repository *repo; | |
| int load_plugin(plugin_repository *repo, char *name) | |
| { | |
| char path[256], init_func_name[128]; | |
| size_t len; | |
| int ret; | |
| void *handle; | |
| plugin *current, *new_plugin; | |
| plugin_init_func init_func; | |
| len = snprintf(path, 256, "%s/%s.so", PLUGIN_BASE_PATH, name); | |
| if (len >= 256) { | |
| fprintf(stderr, "Plugin path name overflowed\n"); | |
| return -1; | |
| } | |
| len = snprintf(init_func_name, 128, "init_%s", name); | |
| if (len >= 128) { | |
| fprintf(stderr, "Plugin func name overflowed\n"); | |
| return -1; | |
| } | |
| printf("Loading plugin %s from file %s\n", name, path); | |
| new_plugin = (plugin *) calloc(1, sizeof(plugin)); | |
| if (repo->plugins == NULL) { | |
| repo->plugins = calloc(1, sizeof(plugin)); | |
| } | |
| current = repo->plugins; | |
| while(current->next) { | |
| current = repo->plugins->next; | |
| } | |
| new_plugin->name = strdup(name); | |
| new_plugin->handle = dlopen(path, RTLD_NOW); | |
| if (!new_plugin->handle) { | |
| fprintf(stderr, "Failed to load plugin %s - object %s not found\n", name, path); | |
| free(new_plugin); | |
| return -1; | |
| } | |
| init_func = (plugin_init_func) (intptr_t) dlsym(new_plugin->handle, init_func_name); | |
| if (!init_func) { | |
| fprintf(stderr, "Failed to find plugin init function %s in %s\n", init_func_name, path); | |
| free(new_plugin); | |
| return -1; | |
| } | |
| ret = init_func(repo); | |
| if (ret < 0) { | |
| fprintf(stderr, "Failed to initialize plugin %s - function %s returned %d\n", name, init_func_name, ret); | |
| return -1; | |
| } | |
| current->next = new_plugin; | |
| fprintf(stderr, "Loaded plugin %s", name); | |
| return 0; | |
| } | |
| int main(int argc, char **argv) | |
| { | |
| int i; | |
| repo = (plugin_repository *) calloc(1, sizeof(plugin_repository)); | |
| for (i = 1; i < argc; i++) | |
| { | |
| load_plugin(repo, argv[i]); | |
| } | |
| return 0; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| all: | |
| gcc -g -o plugin main.c | |
| gcc -o test.so -g -fPIC -shared test.c |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #define PLUGIN_BASE_PATH "/Users/michael/Code/plugins" | |
| typedef struct _plugin plugin; | |
| struct _plugin | |
| { | |
| char *name; | |
| void *handle; | |
| plugin *next; | |
| }; | |
| typedef struct _plugin_repository | |
| { | |
| plugin *plugins; | |
| } plugin_repository; | |
| typedef int (*plugin_init_func)(plugin_repository *); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include "plugin_api.h" | |
| int init_test(plugin_repository *repo) | |
| { | |
| printf("Hello from inside the test plugin\n"); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment