未定义对函数的引用

4

我正在使用Linux,我有以下文件:

main.c, main.h
fileA.c, fileA.h
fileB.cpp, fileB.h

F1() 函数在 fileB.h 中声明,在 fileB.cpp 中定义。我需要在 fileA.c 中使用该函数,因此我将函数声明为:

extern void F1();

fileA.c中。

然而,在编译过程中,我遇到了错误:

fileA.c: (.text+0x2b7): undefined reference to `F1'

有什么问题吗?

谢谢。

预计时间:感谢我收到的答案,现在我有以下内容:

在fileA.h中,我有

#include fileB.h
#include main.h

#ifdef __cplusplus
extern "C" 
#endif
void F1();

在 fileA.c 文件中,我有以下内容:
#include fileA.h

在 fileB.h 文件中,我有以下内容:
extern "C" void F1();

在 fileB.cpp 文件中,我有以下内容:
#include "fileB.h"

extern "C" void F1()
{ }

然而,我现在遇到了错误。
fileB.h: error: expected identifier or '(' before string constant
5个回答

19

如果您确实正在将fileA.c编译为C而不是C ++,那么您需要确保该函数具有适当的、与C兼容的链接。

您可以通过extern关键字的特殊情况来实现。在声明和定义时都要使用:

extern "C" void F1();
extern "C" void F1() {}
否则,C链接器会寻找一个仅以某些混淆的C++名称存在且不受支持的调用约定的函数。 :)
不幸的是,虽然这是在C++中必须做的事情,但在C中语法无效。您必须使extern仅对C++代码可见。
因此,使用一些预处理器技巧:
#ifdef __cplusplus
extern "C"
#endif
void F1();

虽然不太美观,但这是两种语言代码共享一个头文件的代价。


所以现在我的 fileB.h 和 fileB.cpp 分别有 extern "C" void F1(); 和 extern "C" void F1() {},而且 fileA.c 中也有 extern "C" void F1();。但是在编译过程中,我得到了这些错误:“fileB.h: error: expected identifier or "(" before string constant”、“fileA.c: error: expected identifier or "(" before string constant”,还有“fileA.c: warning: implicit declaration of function "F1".” - Rayne
@Tomalak:我仍然在遇到一些错误。请看我对原始条目的编辑。 - Rayne
@Rayne:应该是__cplusplus,而不是__cpluplus。问题在于:你的C代码可以看到函数声明两次。一次来自头文件(你没有使用宏的地方:这是你应该这样做的唯一位置,因为这是跨语言共享的代码),另一次来自fileA.c,在那里你根本不应该编写声明。 - Lightness Races in Orbit
@Tomalak:我已经做出了更改(请参见原始条目中的编辑),但仍然遇到“预期标识符”错误。我不再有“隐式声明”错误。 - Rayne
@Rayne:为什么 fileB.h 声明了头文件?你的 C 代码仍然可以看到一行 extern "C"。考虑一下哪些包含项放在哪里。你应该在一个头文件中声明函数,并在一个源文件中定义它。可以在许多地方包括(多亏了我们的宏技巧)将此头文件包含在 C 源文件中。 - Lightness Races in Orbit
谢谢你的帮助!我现在终于可以编译和链接程序了。 - Rayne

5
为了能够从c源代码中调用c++函数,您需要提供适当的“链接规范”。指定链接规范的格式为:
extern "type_of_Linkage" <function_name>

在您的情况下,您应该使用以下内容:
extern "C" void F1();

4
也许可以使用
extern "C" void F1();

2

fileA.c无法包含fileB.h(通过fileA.h),因为C编译器不知道extern "C"的含义,所以会抱怨在字符串之前看到了标识符。不要尝试在fileA.c或fileA.h中包含fileB.h,这是不必要的。


-1

我认为fileA.c还需要包含fileA.h文件。


包含失败会在编译时产生声明错误,而不是链接时的定义错误。 - Lightness Races in Orbit

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