2013-09-28 96 views
13

我試圖將靜態庫(使用gcc編譯)鏈接到C++程序,並得到'未定義引用'。我在Ubuntu 12.04服務器機器上使用了gcc和g ++版本4.6.3。例如,這裏是因法簡單的庫文件:將C編譯靜態庫鏈接到C++程序

mylib.h

#ifndef __MYLIB_H_ 
#define __MYLIB_H_ 

int factorial(int n); 

#endif 

mylib.c

#include "mylib.h" 

int factorial(int n) 
{ 
    return ((n>=1)?(n*factorial(n-1)):1); 
} 

我使用創建的對象,這mylib.c gcc:

gcc -o mylib.o -c mylib.c 

再次靜態庫是從對象文件中使用AR實用工具創建:

ar -cvq libfact.a mylib.o 

我測試該文庫用C程序(test.c的)和C++程序(TEST.CPP)

C和C++程序具有相同體:

#include "mylib.h" 
int main() 
{ 
    int fact = factorial(5); 
    return 0; 
} 

假設靜態庫libfact.a是在/ home/test目錄可用,我編譯的C程序沒有任何問題:

gcc test.c -L/home/test -lfact 

但是在測試時的C++程序,它投擲鏈接錯誤:

g++ test.cpp -L/home/test -lfact 

test.cpp:(.text+0x2f): undefined reference to `factorial(int)' 
collect2: ld returned 1 exit status 

我甚至試圖在TEST.CPP添加的extern命令:

extern int factorial(int n) //added just before the main() function 

還是一樣的錯誤。

  • 有人能告訴我我在這裏錯了嗎?
  • 創建靜態庫時是否有任何我錯過的東西?
  • 我必須在我的test.cpp中添加任何東西才能使其工作?
+1

當我看到SO問題沒有upvote,還有一個7-upvoted的答案時,我完全理解愚蠢的人類是多麼的愚蠢。如果問題不是這樣的話,答案如何相關?來吧! –

回答

19

問題是你還沒有告訴你的C++程序C語言是用C編寫的。你需要更改你的test.h頭文件。像這樣

#ifndef __MYLIB_H_ 
#define __MYLIB_H_ 

#ifdef __cplusplus 
extern "C" { 
#endif 

int factorial(int n); 

#ifdef __cplusplus 
} 
#endif 

#endif 

現在你的頭文件應該適用於C和C++程序。詳情請參閱here

包含雙下劃線的BTW名稱是爲編譯器保留的(所以名稱以下劃線和大寫字母開頭),因此嚴格來說#ifndef __MYLIB_H_是非法的。我會改爲#ifndef MYLIB_H #define MYLIB_H

+2

是的,它像這樣的魅力。感謝您的鏈接。感謝您添加有關雙下劃線的信息。 – Prabu

+0

很好的解釋。 +1 – Crt

1

雖然接受的答案是絕對正確的,但我認爲我只是添加了一個觀察。某些編輯器在打開/關閉大括號時遇到問題,並會在標頭中縮進整個extern "C"範圍。如果mylib.h是一個圖書館的關鍵標題,你可能會考慮:

#if defined (__cplusplus) 
#define _MYLIB_INIT_DECL extern "C" { 
#define _MYLIB_FINI_DECL } 
#else 
#define _MYLIB_INIT_DECL 
#define _MYLIB_FINI_DECL 
#endif 

所有其它頭在mylib庫,例如,mylib_aux.h,可以是這樣的形式:

#ifndef _MYLIB_AUX_H 
#define _MYLIB_AUX_H 

#include <mylib.h> 

_MYLIB_INIT_DECL 

... header content ... 

_MYLIB_FINI_DECL 

#endif /* _MYLIB_AUX_H */ 

顯然,名字我使用是任意的,但對於多個庫頭文件,這種方法對我很有用。