如果未定义函数,C 中有没有办法让 compiler/linker 给出错误?

Is there a way in C to have the compiler/linker give an error if a function is not defined?

在我的例子中,我使用 dlfcn.h (linux) 在 C 中编写了一个简单的插件系统。插件与主程序分开编译,并生成一堆 .so 文件。

为了让主程序正确调用插件,必须在插件中定义某些功能。理想情况下,我希望每个插件都包含一个 .h 文件或以某种方式说明有效插件必须具有哪些功能的文件,如果这些功能未在插件中定义,我希望插件编译失败。

我认为您不能强制在编译时定义函数。但是,如果您使用 gcc 工具链,则可以在链接时使用 --undefined 标志来强制定义一个符号。

ld --undefined foo

会将 foo 视为一个未定义的符号,必须定义该符号才能使链接器成功。

你不能那样做。

通常的做法是,在 dlopen() 打开的库中只定义两个导出函数,一个在您的插件中导入函数,一个在您的插件中导出函数。

几行代码胜过任何解释:

struct plugin_import {
    void (*draw)(float);
    void (*update)(float);
};
struct plugin_export {
    int (*get_version)(void);
    void (*set_version)(int);
};

extern void import(struct plugin_import *);
extern void export(struct plugin_export *);

int setup(void)
{
    struct plugin_export out = {0};
    struct plugin_import in;

    /* give the plugin our function pointers */
    in.draw = &draw, in.update = &update;
    import(&in);

    /* get our functions out of the plugin */
    export(&out);

    /* verify that all functions are defined */
    if (out.get_version == NULL || out.set_version == NULL)
        return 1;

    return 0;
}

这与 Quake 2 使用的系统非常相似。可以看看出处here
唯一不同的是,Quake 2 只导出了一个函数,即一次性导入和导出动态库定义的函数。

在做了一些研究并询问了一些我在 IRC 上认识的人之后,我找到了以下解决方案:

因为我使用的是 gcc,所以我可以使用 linker 脚本。

linker.script:

ASSERT(DEFINED(funcA), "must define funcA" ) ;
ASSERT(DEFINED(funcB), "must define funcB" ) ;

如果未定义这些函数中的任何一个,则当程序尝试 link 时将输出自定义错误消息。

(有关 linker 脚本语法的更多信息可在此处找到:http://www.math.utah.edu/docs/info/ld_3.html

编译时只需在源文件后添加linker脚本文件:

gcc -o test main.c linker.script

另一种可能性:

引起我注意的是我没有想到(现在看起来有点明显)的事情是您可以创建一个小程序来加载您的插件并检查您是否具有指向所有插件的有效函数指针您希望插件具有的功能。然后将其合并到您的构建系统中,无论是 makefile 还是脚本或其他任何东西。这样做的好处是您不再局限于使用特定的编译器来完成这项工作。您还可以对其他事情进行一些更复杂的检查。唯一的缺点是你需要做更多的工作来设置它。