连接错误:C和C++的未定义引用问题

3

abc.c文件

#include "abc.h"
int abc()
{
    return 10;
}

abc.h file

int abc();

mymain.cpp文件

#include "abc.h"
int main()
{
    abc();
    return  0;
}

Makefile

CC=gcc -O2 
CP=g++

mymain: mymain.o abc.o
    $(CP) -o mymain mymain.o abc.o

mymain.o: mymain.cpp abc.h
    $(CP) -c mymain.cpp abc.h

abc.o: abc.c abc.h
    $(CC) -c abc.c abc.h

clean:  
    $(RM) *.o mymain

输出

g++ -c mymain.cpp abc.h
gcc -O2  -c abc.c abc.h
g++ -o mymain mymain.o abc.o
mymain.o: In function `main':
mymain.cpp:(.text+0x5): undefined reference to `abc()'
collect2: error: ld returned 1 exit status
make: *** [mymain] Error 1

为什么abc()是未定义的引用?

更新

新的abc.h

extern "C" {
    int abc();
}

错误

g++ -c mymain.cpp abc.h
gcc -O2  -c abc.c abc.h
In file included from abc.c:1:0:
abc.h:1:8: error: expected identifier or ‘(’ before string constant
 extern "C" {
        ^
abc.h:1:8: error: expected identifier or ‘(’ before string constant
 extern "C" {
        ^
make: *** [abc.o] Error 1

2
不要将 abc.h 传递给编译器。头文件在被 .c.cpp 文件 #include 时进行处理。 - Keith Thompson
2
另外,“CP”是一个非常糟糕的名称。大多数人会认为你正在尝试复制文件。在makefile中,C++编译器的默认变量名是“CXX”(对于C++编译器特定标志是“CXXFLAGS”)。 - MadScientist
1个回答

9
问题在于你试图将一个C函数链接到一个C++对象中,但没有告诉编译器你正在这样做。
如果你的头文件(abc.h)是这样的:
extern "C" {
    int abc();
}

当它被包含到C++源代码中时,它可以工作...但是当它被包含到C源代码中时就会出问题。

您可以像Combining C++ and C - how does #ifdef __cplusplus work?中所示,将extern "C" {及其尾随的}放入宏中,以便适用于C和C++的包含。

请注意,在您的makefile中,$(CP) -c mymain.cpp abc.h没有意义--您不想在编译器命令行上指定头文件。这对于该模式的两个实例都是如此。


@shantanu 当编译 .c 文件时,你需要有条件地排除它,因为 C 编译器不知道 extern "C" - JustSid
我明白了,这是Makefile。我需要从$(CP) -c mymain.cpp中删除abc.h。 - shantanu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接