2013-09-28 95 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 */ 

显然,名字我使用是任意的,但对于多个库头文件,这种方法对我很有用。