It is possible to implement a static function registry in C for gcc/clang by using the section variable attribute and relying on the ELF linker to define the __start_<section>
and __stop_<section>
symbols pointing to the address of the custom section.
(See below for an example using this approach, which should illustrate the point.)
This approach, however, is very specific to GCC, ELF and Unix/Linux.
Is there an alternative approach to solve this same problem of static function registry, only in a more portable way?
In particular, I would like to be able to target MSVC compiler for Windows.
As an example, consider this program using this set of source files:
1) registry.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) a.c
#include "registry.h"
REGISTER_FUNC(a) {
return 1;
}
3) b.c
#include "registry.h"
REGISTER_FUNC(b) {
return 4;
}
4) c.c
#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) Makefile
registry: main.o a.o b.o c.o
$(CC) -o $@ $^
Build with:
$ 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
Execute with:
$ ./registry
Function a returned 1.
Function b returned 4.
Function cde returned 999.