23

我有一个在 gcc 中使用的 c 库。该库具有扩展名 .lib 但始终作为静态库链接。如果我编写一个将库用作 c 代码的程序,那么一切都很好。但是,如果我将文件重命名为 .cpp (在 c/c++ 中执行简单的操作),我会得到未定义的引用。这些是我为测试目的编写的简单小程序,所以没有花哨的东西。我编译使用:

gcc -g -Wall -I <path to custom headers> -o program main.c customlibrary.lib -lm -lpthread

上面的工作就像一个魅力。然而:

g++ -g -Wall -I <path to custom headers> -o program main.cpp customlibrary.lib -lm -lpthread

或者

gcc -g -Wall -I <path to custom headers> -o program main.cpp customlibrary.lib -lm -lpthread -lstdc++

导致对 customlibrary.lib 中任何函数的未定义引用。我尝试创建一个名为 customlibrary.a 的符号链接,但没有成功。

为什么 g++ find 不能识别我的库。不幸的是,我无法访问库的源代码,但是将 c-lib 链接到 c++ 应该不是问题,对吧?

4

3 回答 3

40

您的库似乎有一个 API 假定它将从 C 调用,而不是 C++。这很重要,因为 C++ 实际上要求从库中导出的符号中包含更多信息,而不仅仅是函数名。这是通过“名称修饰”函数来处理的。

我假设您的库有一个声明其公共接口的包含文件。为了使其与 C 和 C++ 兼容,您应该安排告诉 C++ 编译器它声明的函数应该假定使用 C 的链接和命名。

测试这一点的一个可能简单的答案是这样做:

extern "C" {
#include "customlibrary.h"
}

在您的 main.cpp 中,而不是customlibrary.h直接包含。

为了使头文件本身可以在两种语言中工作并正确地将其函数声明为 C++ 中的 C 类,请将以下内容放在头文件顶部附近:

#ifdef __cplusplus
extern "C" {
#endif

以及底部附近的以下内容:

#ifdef __cplusplus
}
#endif
于 2009-07-01T09:23:25.847 回答
4

C++ 编译器执行所谓的名称修改——出现在代码中的名称与链接器看到的名称不同。解决这个问题的正常方法是告诉编译器某些函数需要 C 链接:

// myfile.cpp
extern "C" int libfun();    // C function in your library

或者对整个头文件执行此操作:

// myfile.cpp
extern "C" {
  #include "mylibdefs.h"      // defs for your C library functions
}
于 2009-07-01T09:23:59.980 回答
2

你的头文件是否有通常的

#ifdef __cplusplus
extern "C" {
#endif

// ...

#ifdef __cplusplus
} /* extern "C" */
#endif

显式地给库函数 C 链接。

.cpp 文件使用 C++ 链接编译,即默认情况下名称修改。

于 2009-07-01T09:23:34.957 回答