Я хочу статически инициализировать структуру, которая будет видна из всех файлов, содержащих некоторый заголовок.
Фактическое намерение состоит в том, чтобы запускать списки функций, указанные во время компиляции, поэтому я хочу инициализировать статически. Я хотел бы поместить списки туда, где они должны быть, в файле, в котором они объявлены или определены.
Надуманный пример:
общий.ч:
struct Widget { int (*a)(); };
фу.ч:
int oof1(void);
int oof2(void);
foo.c:
#include "foo.h"
int oof1(void) { return 1; }
int oof2(void) { return 2; }
struct Widget foo_widgets[] = { {oof1}, {oof2} };
бар.с:
#include "foo.h"
#include "baz.h"
struct Widget *foo_widgets;
struct Widget *baz_widgets;
struct WidgetsContainer {
struct Widget *widget_list;
} wlists[] =
{
{ foo_widgets },
{ baz_widgets }
};
void usage(void) { ... ; process (wlists[i].widget_list); ... }
Это, очевидно, не работает, потому что «элемент инициализатора не является константой» - это потому, что когда компилятор переводит bar.c, он думает, что не знает местоположение foo_widgets (или bar_widgets).
Но так как bar.c #includes foo.h в любом случае, он всегда компилируется вместе с foo.c:
gcc foo.c baz.c bar.c
Поэтому я надеюсь, что есть способ отразить это в исходном коде.
Я не могу объявить foo_widgets
в foo.h, потому что тогда я не смогу инициализировать его, не определяя его несколько раз (поскольку foo.h включен более чем в один файл).
Неэлегантный обходной путь
фу.ч:
...
Widget *get_foos(void) { return foo_widgets; }
бар.с:
...
struct Widget_lists {
struct Widget (*widget_list)();
} wlist[] =
{
{ get_foos },
{ get_bazes }
};
void usage(void) { ...; process(wlist[i].widget_list()); ... }
Есть ли лучший способ?