【问题标题】:Linking C compiled static library to C++ Program将 C 编译的静态库链接到 C++ 程序
【发布时间】:2013-10-04 12:44:40
【问题描述】:

我试图将一个静态库(用 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 中添加任何内容才能使其正常工作?

【问题讨论】:

  • 当我看到没有赞成票的 SO 问题以及 7 票赞成的答案时,我完全理解人类是多么愚蠢。如果问题不相关,答案怎么可能相关?加油!

标签: c++ c linux gcc g++


【解决方案1】:

问题是您没有告诉您的 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

顺便说一句,包含双下划线的名称是为编译器保留的(以下划线和大写字母开头的名称也是如此),因此严格来说#ifndef __MYLIB_H_ 是非法的。我会改成#ifndef MYLIB_H #define MYLIB_H

【讨论】:

  • 是的,它就像魅力一样。感谢您的链接。感谢您添加有关双下划线的信息。
  • 很好的解释。 +1
【解决方案2】:

虽然接受的答案是绝对正确的,但我想我只是添加一个观察。一些编辑器在打开/关闭大括号方面存在问题,并且会在标题中缩进整个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 */

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-26
    • 2012-05-02
    • 1970-01-01
    • 2023-03-19
    • 2012-02-15
    • 1970-01-01
    相关资源
    最近更新 更多