[英]Linking error in simple C program using a C++ header
我正在关注一个介绍教程http://www.linuxinsight.com/files/alp/alp-ch01-getting-started.pdf 。
我创建了源文件main.c,reciprocal.cpp和reciprocal.hpp。 我已经能够成功编译这些文件。 当我去链接它们时出现问题,我收到以下错误消息:
main.o: In function `main':
main.c:(.text+0x30): undefined reference to `reciprocal'
collect2: ld returned 1 exit status
我认为这是不正确地使用头文件,但我真的不知道该尝试什么,因为我已经非常彻底地遵循了这些步骤。
如果有人知道为什么它会抛出那个错误我会非常感激。
谢谢
** UPDATE以下是三个源文件的代码:
main.c中
#include <stdio.h>
#include "reciprocal.hpp"
int main (int argc, char **argv) {
int i;
i = atoi(argv[1]);
printf("The reciprocal of %d is %g\n", i, reciprocal(i));
return 0;
}
reciprocal.cpp
#include <cassert>
#include "reciprocal.hpp"
double reciprocal(int i) {
assert(i != 0);
return 1.0/i;
}
reciprocal.hpp
#ifdef __cplusplus
extern "C" {
#endif
double reciprocal(int i);
#ifdef __cplusplus
}
#endif
我实际上已经修改了自最初发布以来的reciprocal.hpp。 我做的唯一更改是从函数签名中删除extern关键字。 它以前读过
extern double reciprocal(int i);
这个更改允许我链接程序,我现在可以运行它。 我认为可能发生的事情是,第二个外部正在压倒第一个外部。 如果有人对此有任何见解,我会有兴趣知道。
感谢大家的帮助。
将C和C ++代码混合在一起时,可能会遇到麻烦,因为这两种语言具有不同的链接 。 也就是说,如果你要打开已编译的C和C ++文件的目标文件,你会发现这些目标文件中的名称是不同的。
特别是,C ++编译器倾向于使用一种称为“名称修改”的技术,其中函数名称与关于其参数类型的额外信息混合在一起。 例如,一个函数
char foo(int);
可能实际上有内部名称
char@foo@int
在生成的目标文件中。 问题是C代码没有这样做,所以如果你编译了一个C文件并试图引用名称foo
,链接器就找不到它,因为生成的C ++文件中的函数名是char@foo@int
而不是foo
。
为了解决这个问题,C ++有一个功能,允许您明确地告诉链接器不要破坏名称,并使生成的代码看起来像是用于C程序。 为此,您可以声明C ++函数,如下所示:
extern "C" char foo(int);
现在,生成的目标文件将包含名称foo
而不是装饰,其方式与C代码所期望的方式兼容。
要解决您的问题,请尝试将其中一个extern "C"
声明添加到定义reciprocal
C ++源文件中。
注意:如果你有一个混合C和C ++代码的项目,你应该总是将main
函数编译为C ++代码。 C ++将额外的初始化和清理代码引入到C代码中不存在的可执行文件中。 如果将main
编译为C代码,则可能无法将此额外逻辑添加到程序中,因此您可能会在运行时遇到无法解释的崩溃。
希望这可以帮助!
将C ++文件链接到C文件很困难。 C ++“破坏”名称,以便可以发生重载。
您可以通过包含这样的倒数定义来防止错位:
extern "C" {
reciprocal definition...
}
但如果你这样做,你也可以用C语写它...
你能制作一个main.cpp文件吗?
看起来你的reciprocal.hpp
的内容是无效的,可能是#ifdef
行中的拼写错误, __cplusplus
拼写正确(应该有两个下划线)?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.