簡體   English   中英

在C ++文件中使用C extern函數:與Makefile鏈接問題

[英]Using a C extern function inside a C++ file: Linking issues with Makefile

我有一個問題。 我已經在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++重新編譯ac文件,並且該函數定義周圍沒有extern C包裝器。 因此,該名稱將經過C ++處理,並且ao目標文件中將沒有任何print

但是, b.cc會認為print是C名稱(因為它具有 extern C ),因此它將去尋找未修改的版本。

要么在ac中將extern C放在定義周圍(這可能會使它在常規C編譯器中不可用,所以請記住這一點),或者將您的g++命令更改為使用ao (由於它是用以下方法完成的,因此具有無歧義的名稱) C編譯器),而不是ac


實際上,這不起作用,因為您沒有在g++命令中調用鏈接器。 我什至不知道您為什么要嘗試將ao包含在bo 大概最好的時間是在鏈接時創建一個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

如果將ac的編譯更改為使用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編譯器進行ac編譯,因此不會發生名稱修改。 我的建議是清理所有內容(刪除所有*.o文件)並再次運行make ,然后將輸出發布到問題底部。

可能某些文件較舊,這就是為什么在運行make之前應刪除所有目標文件的原因。

您的makefile需要一個鏈接規則,而不是單獨的編譯規則:

CC  = gcc -g
CPP = g++ -g

program: a.o b.o
    ${CPP} -o $@ a.o b.o

早已知道如何將源代碼轉換為目標文件-您無需重新培訓它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM