Imagine that you have an application with a plugin based architecture, where each plugin is a *.so
file that is dynamically loaded with dlopen()
.
The main application can refer to symbols via dlsym()
, and so it may call functions of the plugin. How can the plugin call functions of the main application?
I know that the main application could provide a struct full of function pointers, which the plugin could use to call into the application. Is there any easier way than that?
Edit: here's a minimal working example to show what I mean:
app.h
:
#ifndef APP_H
#define APP_H
void app_utility(void);
#endif
app.c
:
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include "app.h"
void app_utility(void)
{
printf("app_utility()\n");
}
int main(int argc, char **argv)
{
void *handle;
void (*plugin_function)(void);
if (argc < 2) {
fprintf(stderr, "usage: ./app plugin.so\n");
exit(1);
}
handle = dlopen(argv[1], RTLD_NOW | RTLD_LOCAL);
if (!handle) {
fprintf(stderr, "error loading plugin: %s\n", dlerror());
exit(1);
}
plugin_function = dlsym(handle, "doit");
if (!plugin_function) {
fprintf(stderr, "error loading symbol: %s\n", dlerror());
dlclose(handle);
exit(1);
}
plugin_function();
dlclose(handle);
return 0;
}
plugin.c
:
#include <stdio.h>
#include "app.h"
void doit(void)
{
printf("doit()\n");
app_utility();
printf("did it!\n");
}
Example usage:
$ gcc -o app app.c -ldl
$ gcc -shared -o plugin.so
$ ./app ./plugin.so
error loading plugin: ./plugin.so: undefined symbol: app_utility
There is a option you can pass to gcc when you invoke it to create the executable for the main application:
-rdynamic
The GCC documentation for
-rdynamic
:The
ld
manual page for--export-dynamic
includes this paragraph: