首页 > 解决方案 > 在 C 中实现静态函数注册表的可移植方式

问题描述

通过使用节变量属性并依靠 ELF 链接器定义指向自定义节地址的__start_<section>符号__stop_<section>,可以在 C 中为 gcc/clang 实现静态函数注册表。

(请参阅下面的使用这种方法的示例,它应该说明这一点。)

然而,这种方法非常特定于 GCC、ELF 和 Unix/Linux。

是否有另一种方法可以解决同样的静态函数注册表问题,只是以更便携的方式?

特别是,我希望能够针对 Windows 的 MSVC 编译器。


例如,考虑这个程序使用这组源文件:

1) 注册表.h

struct reg_func {
    const char *name;
    int (*func)(void);
};

#define REGISTER_FUNC(name)                     \
    static int func_ ## name(void);             \
    static struct reg_func descr_ ## name       \
        __attribute__((section("registry")))    \
            = { # name, func_ ## name };        \
    static int func_ ## name(void)

extern struct reg_func __start_registry;
extern struct reg_func __stop_registry;

2) 交流

#include "registry.h"

REGISTER_FUNC(a) {
    return 1;
}

3) 公元前

#include "registry.h"

REGISTER_FUNC(b) {
    return 4;
}

4) 抄送

#include "registry.h"

REGISTER_FUNC(cde) {
    return 999;
}

5) main.c

#include <stdio.h>
#include "registry.h"

int main(int argc, char *argv[]) {
    struct reg_func *p;
    for (p = &__start_registry; p < &__stop_registry; p++) {
        printf("Function %s returned %d.\n", p->name, p->func());
    }
    return 0;
}

6) 生成文件

registry: main.o a.o b.o c.o
        $(CC) -o $@ $^

构建:

$ make
cc    -c -o main.o main.c
cc    -c -o a.o a.c
cc    -c -o b.o b.c
cc    -c -o c.o c.c
cc -o registry main.o a.o b.o c.o

执行:

$ ./registry 
Function a returned 1.
Function b returned 4.
Function cde returned 999.

标签: cgcclinkermsvc12

解决方案


推荐阅读