Портативный способ реализации статического реестра функций в C

Реестр статических функций на языке C для gcc/clang можно реализовать с помощью атрибут переменной раздела и полагаясь на компоновщик ELF для определения символы __start_<section> и __stop_<section> указывают на адрес пользовательского раздела.

(См. ниже пример использования этого подхода, который должен проиллюстрировать это.)

Однако этот подход очень специфичен для GCC, ELF и Unix/Linux.

Есть ли альтернативный подход к решению той же проблемы реестра статических функций, только более переносимым способом?

В частности, я хотел бы иметь возможность настроить компилятор MSVC для Windows.


В качестве примера рассмотрим эту программу, используя этот набор исходных файлов:

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) 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) основной.с

#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 $@ $^

Построить с помощью:

$ 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.

person filbranden    schedule 14.12.2018    source источник
comment
Нет. Манипулирование объектными файлами (информация из них) по своей сути зависит от платформы. Если кто-то не написал библиотеку, которая предоставляет общий интерфейс поверх API-интерфейсов конкретной платформы, вы мало что можете сделать (кроме написания общего API самостоятельно).   -  person Jonathan Leffler    schedule 14.12.2018
comment
На самом деле, я думаю, что могу использовать соответствующие #ifdef по мере необходимости... Есть идеи, как это сделать на компиляторе MSVC? Поиски в Google ни к чему не привели, я не уверен, какие ключевые слова приведут меня туда, куда мне нужно...   -  person filbranden    schedule 14.12.2018
comment
Я думаю, что нашел то, что искал... __declspec(allocate("registry$u")) и еще немного магии, чтобы упорядочить разделы до и после этого... stackoverflow. com/a/14783759/9447571   -  person filbranden    schedule 14.12.2018