带有静态库的c ++ undefined引用

时间:2010-04-12 18:06:24

标签: c++ static-libraries

我正在尝试从类中创建一个静态库但是在尝试使用它时,我总是会遇到任何未定义引用的错误。我继续的方式是创建像

这样的目标文件
g++ -c myClass.cpp -o myClass.o

然后用

打包
ar rcs myClass.lib myClass.o

我一般都会忽略这一点。我打赌这是符号的东西。 感谢您的任何建议,我知道这很可能是我在读一些教程时会发现的事情,如果再次打扰愚蠢的东西就很抱歉:)

编辑:

myClass.h:

class myClass{
    public:
        myClass();
        void function();
};

myClass.cpp:

#include "myClass.h"

myClass::myClass(){}
void myClass::function(){}

程序使用类:

#include "myClass.h"

int main(){
myClass mc;
mc.function();

return 0;
}

最后我像这样编译:

g++ -o main.exe -L. -l myClass main.cpp

错误只是经典:

C:\Users\RULERO~1\AppData\Local\Temp/ccwM3vLy.o:main.cpp:(.text+0x31): undefined
 reference to `myClass::myClass()'
C:\Users\RULERO~1\AppData\Local\Temp/ccwM3vLy.o:main.cpp:(.text+0x3c): undefined
 reference to `myClass::function()'
collect2: ld returned 1 exit status

5 个答案:

答案 0 :(得分:103)

这可能是 链接顺序问题。当GNU链接器看到库时,它会丢弃它不需要的所有符号。在这种情况下,您的库出现在.cpp文件之前,因此在编译.cpp文件之前将丢弃该库。这样做:

g++ -o main.exe main.cpp -L. -lmylib

g++ -o main.exe main.cpp myClass.lib

Microsoft链接器不考虑命令行上的库的排序。

答案 1 :(得分:20)

另一个可能的原因:遗忘extern "C"

我遇到了这个,因为我试图将C ++程序与C静态库链接起来。库的头部没有extern "C",因此链接器正在寻找一个受损的函数名,并且该库实际上具有未编码的函数名。

花了一段时间才弄明白发生了什么事,所以我希望这有助于其他人。

答案 2 :(得分:5)

使用:

g++ -o main.exe main.cpp myClass.lib 

使用库路径和-l标志充满了问题,但如果必须这样做,请将库重命名为libmylib.a,然后编译为:

g++ -o main.exe main.cpp -L. -lmylib 

另请注意,出于可移植性的原因,在源文件或输出文件的名称中使用混合大小写通常是个坏主意。

答案 3 :(得分:5)

这是链接器如何优化输出代码的问题。 让我们假设我们有一个使用两个库的可执行文件: Lib_A Lib_B Lib_A 取决于 Lib_B Lib_A 定义符号: Lib_A1 Lib_A2 Lib_B 定义符号 Lib_B1 Lib_B2 。 现在假设可执行文件仅使用符号 Lib_A1 Lib_A1 使用 Lib_B 中定义的符号 Lib_B1 。符号 Lib_B1 从不在可执行文件中使用。

  1. 对于windows,链接器的工作原理如下:我有两个可执行文件,它使用一些库和可执行文件中使用的所有符号,所有库都是 lib_A1 lib_B1 。因此,我将需要这两个符号,其余的是不必要的。我将取消定义 lib_A2 lib_B2
  2. 对于Linux,如果您在 Lib_A 之前链接 Lib_B ,请执行以下操作: g++ .... -lLib_B -lLib_A 链接器的工作方式如下:我的可执行文件首先链接 Lib_B 。我没有看到可执行文件使用符号 Lib_B1 Lib_B2 。它们是不必要的,因此我将取消定义它们。后来链接器看到了。哦,我有另一个库 Lib_A 。我可以看到可执行文件使用符号 Lib_B1 。我将保留它并取消定义未使用的符号 Lib_B2 。它没有看到 Lib_B1 使用 Lib_A1 ,这已经是未定义的。
  3. 如果是linux,如果您在 Lib_B 之前链接 Lib_A ,请执行以下操作: g++ ... -lLib_A -lLib_B 链接器的工作方式如下:我的可执行文件首先链接 Lib_A 。哦,我可以看到可执行文件使用 Lib_A1 。我将保留它们并取消定义 Lib_A2 。后来它可以看到。哦,我有另一个库 Lib_B 。我可以看到现在可执行的已经链接的符号,使用 Lib_B1 ,我会保留它们。因此,它保留 Lib_B1 Lib_A1 ,以及未定义的 Lib_B2 Lib_A2

答案 4 :(得分:1)

这应避免链接错误并创建.so共享库:

LOCAL_ALLOW_UNDEFINED_SYMBOLS := true