main的多个定义->如何仅从另一个标头添加一些功能?

时间:2019-03-15 18:48:11

标签: c linker

在C中,我得到链接器错误“ main”的多个定义。是的,没错,但是:

为什么链接器尝试包含第二个(ext.c)主函数,尽管我刚刚包含了头文件ext.h?我希望链接器仅链接已找到其原型或初始main需要的函数?

我该如何解决 a)测试编译并且链接没有问题(只需使用ext.c中的func())即可 b)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 个答案:

答案 0 :(得分:6)

您的外部模块不应具有public class AddPartition <R extends ConnectRecord<R>> implements Transformation<R> { public static final ConfigDef CONFIG_DEF = new ConfigDef(); @Override public void configure(Map<String, ?> props) { final SimpleConfig config = new SimpleConfig(CONFIG_DEF, props); } @Override public R apply(R record) { return record.newRecord(record.topic(), calculatePartition(record), record.keySchema(), record.key(), record.valueSchema(), record.value(), record.timestamp()); } private Integer calculatePartition(R record) { // Partitions calcuation based on record information return 0; } @Override public void close() { } @Override public ConfigDef config() { return CONFIG_DEF; } } ,因为它是模块而不是应用程序。您只需将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

答案 1 :(得分:1)

在C语言中,链接到可执行文件的所有文件中只能有一个函数的定义。没有一种方法告诉编译器“我要使用此main()而不是其他所有代码”。 (使用宏有一种不好的方法,但这很麻烦。)

如果要使用具有两个不同的main()函数的函数,请将其放在单独的文件中。

答案 2 :(得分:0)

我想您的编译/链接调用就像

gcc test.c ext.c

在这种情况下,test.c和ext.c(确切地说是从其中创建的.o文件)是对等体,即。 e。在同一水平上。链接器应如何知道采用哪个版本的符号main以及放弃哪个版本?链接器不知道所使用的包含文件。

对于主要功能,正确的方法是在您的项目中确切使用其中之一。

对于具有此要求的任何其他功能,有几种方法可供选择:

您可以将其中之一声明为“弱”。如果存在“强”,则将其丢弃。

或者您将函数放入库中,例如G。 libext.a。如果将其与-ext链接,则只有定义了未定义符号的目标文件会从其中取出。但是话又说回来,如果已经定义了该对象文件定义的另一个名称,则可能发生名称冲突。因此,最好在每个目标文件中尽可能少地定义符号。