libdl 加载的 "plugins" 如何引用加载它们的程序中的符号?

How can "plugins" loaded by libdl refer to symbols in the program which loaded them?

假设您有一个基于插件架构的应用程序,其中每个插件都是一个 *.so 文件,该文件使用 dlopen().

动态加载

主应用程序可以通过dlsym()引用符号,因此它可以调用插件的函数。插件如何调用主应用的功能?

我知道主应用程序可以提供一个充满函数指针的结构,插件可以使用它来调用应用程序。还有比这更简单的方法吗?

编辑:这里有一个最小的工作示例来说明我的意思:

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");
}

用法示例:

$ gcc -o app app.c -ldl
$ gcc -shared -o plugin.so
$ ./app ./plugin.so
error loading plugin: ./plugin.so: undefined symbol: app_utility

当您调用它为主应用程序创建可执行文件时,您可以将一个选项传递给 -rdynamic

$ gcc -rdynamic -o app app.c -ldl

对于-rdynamicGCC documentation

Pass the flag -export-dynamic to the ELF linker, on targets that support it. This instructs the linker to add all symbols, not only used ones, to the dynamic symbol table. This option is needed for some uses of dlopen or to allow obtaining backtraces from within a program.

--export-dynamicld manual page 包括这段:

If you use "dlopen" to load a dynamic object which needs to refer back to the symbols defined by the program, rather than some other dynamic object, then you will probably need to use this option when linking the program itself.