链接不同版本的共享库

时间:2016-05-26 22:50:35

标签: c++ c gcc linker g++

我有两个版本的共享库: 库版本2:

simple.h

#pragma once
int first(int x);

simple.c

#include "simple.h"
#include <stdio.h>

__asm__(".symver first_1_0,first@LIBSIMPLE_1.0");
int first_1_0(int x)
{
    printf("lib: %s\n", __FUNCTION__);
    return x + 1;
}

__asm__(".symver first_2_0,first@@LIBSIMPLE_2.0");
int first_2_0(int x)
{
    int y;
    printf("lib: %d\n", y);
    printf("lib: %s\n", __FUNCTION__);
    return (x + 1) * 1000;
}

链接器版本脚本文件:

LIBSIMPLE_1.0{
    global:
    first;
    local:
    *;
};

LIBSIMPLE_2.0{
    global:
    first;
    local:
    *;
};

gcc -Wall -g -O0 -fPIC -c simple.c
gcc -shared simple.o -Wl,--version-script,script -o libsimple.so.2.0.0

和图书馆版本3:

simple.h

#pragma once  
#ifdef SIMPLELIB_VERSION_3_0
int first(int x, int normfactor);
#else
int first(int x);
#endif //SIMPLELIB_VERSION_3_0

simple.c

#include "simple.h"
#include <stdio.h>

__asm__(".symver first_1_0,first@LIBSIMPLE_1.0");
int first_1_0(int x)
{
    printf("lib: %s\n", __FUNCTION__);
    return x + 1;
}

__asm__(".symver first_2_0,first@LIBSIMPLE_2.0");
int first_2_0(int x)
{
    printf("lib: %s\n", __FUNCTION__);
    return (x + 1) * 1000;
}

__asm__(".symver first_3_0,first@@LIBSIMPLE_3.0");
int first_3_0(int x, int normfactor)
{
    printf("lib: %s\n", __FUNCTION__);
    return (x + 1) * normfactor;
}

链接器版本脚本文件:

LIBSIMPLE_1.0{
    global:
    first; second;
    local:
    *;
};

LIBSIMPLE_2.0{
    global:
    first;
    local:
    *;
};

LIBSIMPLE_3.0{
    global:
    first;
    local:
    *;
};

gcc -Wall -g -O0 -fPIC -c simple.c
gcc -shared simple.o -Wl,--version-script,script -o libsimple.so.3.0.0

所以我最终得到了两个不同的库。接下来我创建一个简单的应用程序,最终我想链接到库版本3,所以在其中我使用函数first(),它接受两个参数:

的main.c

#include <stdio.h>
#include "simple.h"

int main(int argc, char* argv[])
{
    int nFirst = first(1, 10);
    printf("First(1) = %d\n", nFirst);
}

我使用下一个命令编译应用程序:

gcc -g -Wall -DSIMPLELIB_VERSION_3_0 -c main.c 

然后,偶然地,我没有链接到库版本3,而是链接到库版本2.我希望链接失败,但它经历了,应用程序正在运行。

gcc main.o -Wl,-L. -lsimple.2.0.0 -Wl,-R. -o demo

所以我的问题是:

  1. 是因为库导出带有名称&#39; function&#39;的符号,并且应用程序尝试链接到相同的符号名称,这就是链接器没有抱怨的原因,只是链接到库版本2 ?
  2. 我认为,因为c ++破坏符号名称,这样的事情不会发生,链接器也不会链接到库版本2.所以我尝试了所有相同的,但我没有尝试gcc编译器,使用g ++。一切顺利,直到我试图将应用程序链接到库,我收到未解决的链接错误。无法弄清楚原因。
  3. P.S。很抱歉有大量代码。我试图说清楚。 谢谢

1 个答案:

答案 0 :(得分:2)

  

是因为库导出带有名称'function'的符号,并且应用程序尝试链接到相同的符号名称,这就是链接器没有抱怨的原因,只是链接到库版本2?

是的,因为普通C没有函数重载,所以不需要修改,因此只有函数名称将用作链接的符号。最后,您的应用程序代码想要与function和您的库代码导出function,这足以让链接器满意(即使它从二进制接口的角度看无效。)

  

我认为,因为c ++破坏了符号名称,所以这种情况不会发生,并且链接器也不会链接到库版本2.所以我尝试了所有相同的,但我尝试使用g ++而不是gcc编译器。一切顺利,直到我试图将应用程序链接到库,我收到未解决的链接错误。无法弄清楚原因。

是的,由于名称错误,C ++中不应该出现此问题。但是,只有在C ++中同时包含应用程序代码库代码,或者以正确的方式桥接C和C ++代码时,才会出现这种情况。

很难说(没有完整列表)当你使用g ++时你的情况发生了什么,但从它的外观来看,你最终在C ++和库代码中应用程序代码 / em>仍在C中。如果是这种情况,您的应用程序代码现在想要与错误的function链接,而您的库代码仍然导出未编译的{{ 1}}。

要验证这一点,您可以使用以下内容检查目标文件:

function

...并确切地看到它想要什么样的符号。如果你得到这样的东西:

nm main.o

...而不是:

...
    U _Z3functionii
...

......那就是这种情况。

要“修复”此问题并使用库代码中未编译的... U function ... 进行C ++ 应用程序代码链接,您需要将函数原型声明为{ {1}}。