gpt4 book ai didi

c++ - 在 C++ 文件 : Linking issues with Makefile 中使用 C extern 函数

转载 作者:太空宇宙 更新时间:2023-11-04 00:42:19 24 4
gpt4 key购买 nike

我有一个问题。我在 C 文件 read-line.c 中定义了一个打印函数,如下所示:

void history_print(void)
{
/* some stuff */
}

在 C++ 文件 command.cc 中,我有以下内容:

extern "C" void history_print(void);

然后我只需调用 history_print()。

#Use GNU compiler
cc = gcc -g
CC = g++ -g

all: shell

tty-raw-mode.o: tty-raw-mode.c
gcc -c tty-raw-mode.c

read-line.o: read-line.c
gcc -c read-line.c

lex.yy.o: shell.l
lex shell.l
$(cc) -c lex.yy.c

y.tab.o: shell.y
yacc -d shell.y
$(CC) -c y.tab.c

command.o: command.cc
$(CC) -c command.cc

shell: y.tab.o lex.yy.o tty-raw-mode.o read-line.o command.o
$(CC) -o shell lex.yy.o y.tab.o tty-raw-mode.o read-line.o command.o -ll -lgen

我在 Makefile 中为规则输出链接时遇到问题:

Undefined                       first referenced
symbol in file
history_print command.o
ld: fatal: Symbol referencing errors. No output written to shell
collect2: ld returned 1 exit status
*** Error code 1
make: Fatal error: Command failed for target `shell'

make 的 -v 选项标志的输出:

yacc -d shell.y
g++ -g -v -c y.tab.c
Reading specs from /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/specs
Configured with: ../sources/gcc-3.4.6/configure --prefix=/opt/csw/gcc3 --with-local- prefix=/opt/csw --without-gnu-as --with-as=/usr/ccs/bin/as --without-gnu-ld --with-ld=/usr/ccs/bin/ld --enable-threads=posix --enable-shared --enable-multilib --enable-nls --with-included-gettext --with-libiconv-prefix=/opt/csw --with-x --enable- java-awt=xlib --enable-languages=all
Thread model: posix
gcc version 3.4.6
/opt/csw/gcc3/libexec/gcc/sparc-sun-solaris2.8/3.4.6/cc1plus -quiet -v y.tab.c -quiet -dumpbase y.tab.c -mcpu=v7 -auxbase y.tab -g -version -o /var/tmp//ccCi8vXj.s
ignoring nonexistent directory "/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../.. /../../sparc-sun-solaris2.8/include"
#include "..." search starts here:
#include <...> search starts here:
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../include/c++/3.4.6
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../include/c++/3.4.6/sparc- sun-solaris2.8
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../include/c++/3.4.6/backward
/opt/csw/include
/opt/csw/gcc3/include
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/include
/usr/include
End of search list.
GNU C++ version 3.4.6 (sparc-sun-solaris2.8)
compiled by GNU C version 3.4.6.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
/usr/ccs/bin/as -V -Qy -s -xarch=v8 -o y.tab.o /var/tmp//ccCi8vXj.s
/usr/ccs/bin/as: SunOS 5.10 118683-05 Patch 04/30/2010
lex shell.l
gcc -g -c lex.yy.c
gcc -c tty-raw-mode.c
gcc -c read-line.c
g++ -g -v -c command.cc
Reading specs from /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/specs
Configured with: ../sources/gcc-3.4.6/configure --prefix=/opt/csw/gcc3 --with-local- prefix=/opt/csw --without-gnu-as --with-as=/usr/ccs/bin/as --without-gnu-ld --with-ld=/usr/ccs/bin/ld --enable-threads=posix --enable-shared --enable-multilib --enable-nls --with-included-gettext --with-libiconv-prefix=/opt/csw --with-x --enable- java-awt=xlib --enable-languages=all
Thread model: posix
gcc version 3.4.6
/opt/csw/gcc3/libexec/gcc/sparc-sun-solaris2.8/3.4.6/cc1plus -quiet -v command.cc -quiet -dumpbase command.cc -mcpu=v7 -auxbase command -g -version -o /var/tmp//cckVWlC7.s
ignoring nonexistent directory "/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../sparc-sun-solaris2.8/include"
#include "..." search starts here:
#include <...> search starts here:
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../include/c++/3.4.6
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../include/c++/3.4.6/sparc-sun-solaris2.8
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../include/c++/3.4.6/backward
/opt/csw/include
/opt/csw/gcc3/include
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/include
/usr/include
End of search list.
GNU C++ version 3.4.6 (sparc-sun-solaris2.8)
compiled by GNU C version 3.4.6.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
/usr/ccs/bin/as -V -Qy -s -xarch=v8 -o command.o /var/tmp//cckVWlC7.s
/usr/ccs/bin/as: SunOS 5.10 118683-05 Patch 04/30/2010
g++ -g -v -o shell lex.yy.o y.tab.o tty-raw-mode.o read-line.o command.o -ll -lgen
Reading specs from /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/specs
Configured with: ../sources/gcc-3.4.6/configure --prefix=/opt/csw/gcc3 --with-local- prefix=/opt/csw --without-gnu-as --with-as=/usr/ccs/bin/as --without-gnu-ld --with-ld=/usr/ccs/bin/ld --enable-threads=posix --enable-shared --enable-multilib --enable-nls --with-included-gettext --with-libiconv-prefix=/opt/csw --with-x --enable- java-awt=xlib --enable-languages=all
Thread model: posix
gcc version 3.4.6
/opt/csw/gcc3/libexec/gcc/sparc-sun-solaris2.8/3.4.6/collect2 -V -R /opt/csw/lib -Y P,/opt/csw/lib:/usr/ccs/lib:/usr/lib -Qy -o shell /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/crt1.o /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/crti.o /usr/ccs/lib/values-Xa.o /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/crtbegin.o -L/opt /csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6 -L/usr/ccs/bin -L/usr/ccs/lib -L/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../.. lex.yy.o y.tab.o tty-raw-mode.o read-line.o command.o -ll -lgen -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc -lc /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/crtend.o /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/crtn.o
ld: Software Generation Utilities - Solaris Link Editors: 5.10-1.497
Undefined first referenced
symbol in file
history_print command.o
ld: fatal: Symbol referencing errors. No output written to shell
collect2: ld returned 1 exit status
*** Error code 1
make: Fatal error: Command failed for target `shell'

我猜问题出在链接上,它与 Makefile 有关,但我不确定如何解决。谁能帮帮我?

非常感谢,非常感谢您的帮助。

贾里

最佳答案

这是因为您正在使用 g++ 重新编译 a.c 文件,并且函数定义周围没有 extern C 包装器。因此,该名称将经过 C++ 处理,并且 a.o 目标文件中不会有 print

但是,b.cc 会认为 print 是一个 C 名称(因为它 extern C) 所以它将去寻找未损坏的版本。

要么将 extern C 放在 a.c 中的定义周围(这可能会使常规 C 编译器无法使用,因此请记住这一点)或更改您的 g++ 命令使用 a.o(由于它是用 C 编译器完成的,所以它具有未损坏的名称)而不是 a.c


事实上,这是行不通的,因为您没有在 g++ 命令中调用链接器。我什至不确定为什么您要将a.o 包含到b.o 中。可能最好的时间是在链接时创建一个 ab 可执行文件,而不是编译时,比如:

CC = g++ -g

a.o: a.c
gcc -o a.o -c a.c

b.o: b.cc
$(CC) -o b.o -c b.cc

ab: a.o b.o
$(CC) -o ab a.o b.o

更新:将其分解为最简单的测试用例,以便您明白我的意思:

a.c:
#include <stdio.h>
void print(void) {
printf ("7\n");
}

b.cc:
extern "C" void print(void);
int main(void) {
print();
return 0;
}

Makefile:
output: a.o b.o Makefile
g++ -o output a.o b.o

a.o: a.c Makefile
gcc -o a.o -c a.c

b.o: b.cc Makefile
g++ -o b.o -c b.cc

然后运行 ​​make 和程序:

pax> make
gcc -o a.o -c a.c
g++ -o b.o -c b.cc
g++ -o output a.o b.o

pax> ./output
7

如果您将 a.c 的编译更改为使用 g++,则会出现原始错误,即无法找到 print:

pax> make
g++ -o a.o -c a.c
g++ -o b.o -c b.cc
g++ -o output a.o b.o
b.o:b.cc:(.text+0x2b): undefined reference to `_print'
collect2: ld returned 1 exit status
make: *** [output] Error 1

现在看来您的最终 Makefile 是正确的。它使用 C 编译器编译 a.c,因此不会发生名称重整。我的建议是清理所有内容(删除所有 *.o 文件)并再次运行 make,然后将输出发布在问题的底部。

可能有些文件是旧文件,这就是为什么您应该在运行 make 之前删除所有目标文件。

关于c++ - 在 C++ 文件 : Linking issues with Makefile 中使用 C extern 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3723863/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com