Учитывая библиотечный модуль, в следующем называемом Runner
, который находится в качестве повторно используемого компонента (не требуется перекомпиляции, то есть статическая библиотека ссылок) в разделе приложения архитектуры, а не в главном разделе. Обратите внимание, что он содержит только main()
для демонстрационных целей.
Учитывая набор (не относящийся к делу) других модулей/объектов, называемых Callable
s, т.е. Callable1
, Callable2
и Callable3
, которые также находятся в качестве повторно используемых компонентов в разделе приложения.
Runner
имеет зависимость от времени выполнения от Callable
в том, что Runner
должен знать каждый из этих Callable
, чтобы получить данные от них (получить доступ к структуре) или выполнить их операцию ( вызовите функцию).
Runner
не должен зависеть от компиляции с Callable
s. Вместо этого зависимости должны быть введены через компоновщик в фиктивный модуль Callables
.
Концепция должна использоваться не только в размещенной среде, но и в автономной среде. Поэтому механизмы загрузки, такие как загрузка Callable
в качестве общих объектов во время выполнения, не могут быть использованы.
Как можно вводить зависимости с помощью компоновщика?
Мое рабочее решение состоит в том, чтобы указать указатели 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
, но меня очень интересуют решения, которые менее специфичны для инструментальной цепочки/более переносимы, чем решение, которое я нашел до сих пор.