Инъекция N-зависимостей в C - лучший способ, чем массивы, определенные линкерами?

Учитывая модуль библиотеки, в следующем называется Runner, который находится как компонент многократного использования (перекомпиляция не требуется, то есть статическая библиотека ссылок) в разделе приложения архитектуры, а не в основном разделе. Обратите внимание, что он содержит только main() для демонстрационных целей.

Данный набор (не относящийся к порядку) других модулей / объектов называется Callableс, т.е. Callable1, Callable2 а также Callable3, которые также находятся как многократно используемые компоненты в разделе приложения.

Runner имеет зависимость во время выполнения от Callableв этом Runner должен знать каждый из этих Callables для того, чтобы получить данные из них (получить доступ к структуре) или заставить их выполнить операцию (вызвать функцию).

Runner не должно зависеть от компиляции Callables. Вместо этого зависимости должны быть введены через компоновщик в фиктивный модуль Callables, Концепция должна быть применима не только в размещенной среде, но и в автономной среде. Таким образом, механизмы на основе загрузчика, такие как загрузка Callables как общие объекты во время выполнения не могут быть использованы.

Как можно ввести зависимости с помощью компоновщика?

Мое рабочее решение, позволяя Callableопределить указатели в выделенном разделе, в данном случае с именем Callables, который компоновщик будет собирать так, чтобы Runner может получить к нему доступ, получая необходимую информацию во время ссылки.

Callable.h

#ifndef CALLABLE_H
#define CALLABLE_H
typedef void (*Callable)(void);
#endif

Callables.h

#ifndef CALLABLES_H
#define CALLABLES_H
#include "Callable.h"
extern Callable Callables_start[];
extern Callable Callables_end[];
#endif

Runner.c

#include "Callables.h"
void Runner_run(void) {
    for (Callable *callables = Callables_start; callables < Callables_end; callables++)
        (*callables)();
}
int main(void) {
    Runner_run();
    return 0;
}

Callable1.c

#include <stdio.h>
#include "Callable.h"
static void Callable1_call(void) {
    printf("Callable 1\n");
}
static Callable thisCallable __attribute__((section("Callables"))) = &Callable1_call;

Callable2.c а также Callable3.c выглядят одинаково, за исключением другого сообщения в printf(),

Callables.ld

PROVIDE(Callables_start = LOADADDR(Callables));
PROVIDE(Callables_end = Callables_start + SIZEOF(Callables));

Makefile

CFLAGS+=--std=c99
callables:=Callable1 Callable2 Callable3
.PHONY: all
all: Runner

Runner: Callables.ld Runner.o $(addsuffix .o, $(callables))

Выход

$ make -s && ./Runner
Callable 1
Callable 2
Callable 3

Вывод показывает, что решение работает, но я не удовлетворен решением. Каковы альтернативные, желательно лучшие способы внедрения зависимостей с использованием компоновщика, чем решение, которое я нашел?

Заметка

Среда GCC / LD на x86_64 с -ffreestanding, но я очень заинтересован в решениях, которые менее специфичны для инструментария / более портативны, чем решение, которое я нашел до сих пор.

0 ответов

Другие вопросы по тегам