Как создавать модули в C - PullRequest
       35

Как создавать модули в C

1 голос
/ 21 декабря 2010

У меня есть интерфейс, с которым я хочу иметь возможность статически связывать модули.Например, я хочу иметь возможность вызывать все функции (хотя и в отдельных файлах) с именем FOO или соответствующие определенному прототипу, в конечном итоге сделать вызов функции в файле без заголовка в других файлах.Не говорите, что это невозможно, так как я нашел хак, который может это сделать, но я хочу не взломанный метод.(Хак - использовать nm для получения функций и их прототипов, тогда я могу динамически вызывать функцию).Кроме того, я знаю, что вы можете сделать это с помощью динамического связывания, однако я хочу статически связать файлы.Есть идеи?

Ответы [ 4 ]

5 голосов
/ 21 декабря 2010

Поместите таблицу всех функций в каждую единицу перевода:

struct functions MOD1FUNCS[]={
     {"FOO", foo},
     {"BAR", bar},
     {0, 0}
};

Затем поместите таблицу в основную программу со списком всех этих таблиц:

struct functions* ALLFUNCS[]={
    MOD1FUNCS,
    MOD2FUNCS,
    0
};

Затем во время выполнения, поиск по таблицам и поиск соответствующего указателя на функцию.

3 голосов
/ 21 декабря 2010

Это довольно часто встречается при написании тестового кода. например, вы хотите вызвать все функции, которые начинаются с test_. Таким образом, у вас есть сценарий оболочки, который grep просматривает все ваши файлы .C и извлекает имена функций, которые соответствуют test _. *. Затем этот скрипт генерирует файл test.c, который содержит функцию, которая вызывает все функции теста.

Например, сгенерированная программа будет выглядеть так:

int main() {
   initTestCode();
   testA();
   testB();
   testC();
}

Еще один способ сделать это - использовать некоторые трюки с линкерами. Это то, что ядро ​​Linux делает для своей инициализации. Функции, которые являются кодом инициализации, отмечены квалификатором __init. Это определяется в linux / init.h следующим образом:

#define __init          __section(.init.text) __cold notrace

Это заставляет компоновщик поместить эту функцию в раздел .init.text. Ядро будет восстанавливать память из этого раздела после загрузки системы.

Для вызова функций каждый модуль объявляет функцию initcall с некоторыми другими макросами core_initcall (func), arch_initcall (func) и так далее (также определенными в linux / init.h). Эти макросы помещают указатель на функцию в секцию компоновщика с именем .initcall.

Во время загрузки ядро ​​будет "проходить" через раздел .initcall, вызывая все указатели там. Код, который просматривается, выглядит следующим образом:

extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];

static void __init do_initcalls(void)
{
        initcall_t *fn;

        for (fn = __early_initcall_end; fn < __initcall_end; fn++)
                do_one_initcall(*fn);

        /* Make sure there is no pending stuff from the initcall sequence */
        flush_scheduled_work();
}

Символы __initcall_start, __initcall_end и т. Д. Определяются в сценарии компоновщика.

В целом, ядро ​​Linux делает некоторые из самых хитрых трюков с препроцессором, компилятором и компоновщиком GCC, которые возможны. Это всегда было отличным ориентиром для трюков на Си.

0 голосов
/ 21 декабря 2010

Я действительно не думаю, что вы можете сделать это.С не совсем способен к позднему связыванию или виду самоанализа, который вам, кажется, требуется.

Хотя я не совсем понимаю ваш вопрос.Хотите ли вы возможности динамически связанных библиотек при статической компоновке?Поскольку это не имеет смысла для меня ... для статической ссылки, вам нужно уже иметь бинарный файл под рукой, что сделало бы динамическую загрузку функций пустой тратой времени, даже если бы вы могли легко это сделать.

0 голосов
/ 21 декабря 2010

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

Вам, безусловно, нужен какой-то механизм для регистрации доступных функций.Динамическое связывание обеспечит именно это.

...