несколько определений main -> как добавить только некоторые функции из другого заголовка? - PullRequest
0 голосов
/ 15 марта 2019

В C я получаю многократное определение ошибки компоновщика `main '. Да, это правда, но:

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

Как я могу решить это, а) тест компилируется и связывается без проблем (просто используйте func () из ext.c) и б) также можно скомпилировать и связать ext.c как отдельное приложение?

(пример) код:

//file: test.c
#include "/home/stefanm/test/test.h"

void main (int argc, char * argv[])
{
    uint8_t var = 123;
    printf ("main(): var= %i\n", var);
    func (var);
                                                                                                                    }
//file: test.h
#ifndef TEST_H
#define TEST_H
#include <the rest>
#include "/home/stefanm/test/ext.h"                                                                                                                     
#endif

... и внешний модуль:

//file: ext.c
#include "/home/stefanm/test/ext.h"
uint8_t func (uint8_t i){    
    printf ("func(): Variable i is %i", i); 
    return 0;
}

void main () {
    printf ("ext main func");
}   
//file: ext.h
#ifndef EXT_H
#define EXT_H
#include "all needed headers"  

uint8_t func (uint8_t);
#endif    

Я вызываю компилятор с gcc test.c ext.c -o test

Ответы [ 3 ]

6 голосов
/ 15 марта 2019

Ваш внешний модуль не должен иметь main(), потому что это модуль, а не приложение.Вам нужно просто переместить main() из вашего модуля в отдельный файл:

//file: app.c
#include "/home/stefanm/test/ext.h" // <-- BTW, using absolute paths is not a good idea

void main () {
    //use function from ext here
    printf ("app main func");
}

, а затем скомпилировать ваше приложение так:

gcc app.c ext.c

и ваш тест так:

gcc test.c ext.c
1 голос
/ 15 марта 2019

В C вы можете иметь только одно определение функции во всех файлах, которые вы ссылаете на свой исполняемый файл.Нет хорошего способа сказать компилятору "Я хочу использовать этот main(), а не все остальные".(Есть плохой способ использования макросов, но это было бы грязно).

Если вы хотите использовать функцию с двумя разными main() функциями, поместите ее в отдельный файл.

0 голосов
/ 15 марта 2019

Полагаю, ваш вызов компиляции / ссылки идет как

gcc test.c ext.c

В этом случае test.c и ext.c (а точнее, файлы .o, созданные из них) являются равноправными, т.е. е. на том же уровне. Как компоновщик должен знать, какую версию символа main взять, а какую отказаться? Компоновщик не знает об используемых файлах включения.

В случае с основной функцией правильный путь - использовать в своем проекте ровно одну из них.

Для любой другой функции, для которой у вас есть это требование, есть несколько способов:

Либо вы могли бы объявить одного из них "слабым". Он будет отброшен, когда будет "сильный".

Или вы поместили свою функцию в библиотеку, e. г. libext.a. Если вы свяжете это с -ext, из него будут удалены только объектные файлы, которые определяют символы, которые не определены. Но опять же, конфликт имен может произойти, если уже определено другое имя, определенное этим объектным файлом. Поэтому лучше всего определять как можно меньше символов в объектном файле.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...