将C编译的静态库链接到C++程序中。

8 浏览
0 Comments

将C编译的静态库链接到C++程序中。

我尝试将一个使用gcc编译的静态库链接到一个C++程序中,但是出现了“未定义的引用”的错误。我在一个Ubuntu 12.04服务器上使用gcc和g++版本4.6.3。例如,这是一个简单的用于阶乘方法的库文件:

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);
}

我使用gcc为这个mylib.c文件创建了一个对象:

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中添加什么才能使它工作?
0
0 Comments

问题出现的原因是一些编辑器在处理开/闭括号时会出现问题,会对头文件中的整个extern "C"范围进行缩进。为了解决这个问题,可以使用预处理指令来定义宏,根据是否是C++程序来决定是否需要添加extern "C"。

解决方法如下:

1. 在mylib.h头文件中,根据是否是C++程序来定义宏_MYLIB_INIT_DECL和_MYLIB_FINI_DECL,如果是C++程序则定义为extern "C",否则为空。

2. 在其他mylib库的头文件中,例如mylib_aux.h,在包含mylib.h之前,使用#ifndef指令来判断该头文件是否已经被包含过,如果没有则定义宏_MYLIB_INIT_DECL为extern "C",否则为空。在头文件内容的末尾使用宏_MYLIB_FINI_DECL来结束extern "C"范围。

这种方法可以解决编辑器在处理extern "C"时的缩进问题,使得多个库头文件可以正常链接。

0
0 Comments

问题的原因是你没有告诉你的C++程序factorial是用C语言编写的。你需要更改你的test.h头文件,像这样:

#ifndef __MYLIB_H_
#define __MYLIB_H_
#ifdef __cplusplus
extern "C" {
#endif
int factorial(int n);
#ifdef __cplusplus
}
#endif
#endif

现在你的头文件应该适用于C和C++程序。详情请参见这里

顺便说一下,双下划线命名的名称是保留给编译器的(以及以下划线和大写字母开头的名称),所以#ifndef __MYLIB_H_严格来说是不合法的。我会改为#ifndef MYLIB_H #define MYLIB_H

是的,用这个方法很好用。感谢你提供的链接。感谢你添加关于双下划线的信息。

很好的解释。+1

0