【问题标题】:Linking on different version of shared libraries链接不同版本的共享库
【发布时间】:2016-05-26 22:50:35
【问题描述】:

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

简单的.h

#pragma once
int first(int x);

简单的.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:

简单的.h

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

简单的.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. 是因为库导出了名为“function”的符号,而应用程序尝试链接到相同的符号名称,这就是为什么链接器没有抱怨,而是链接到库版本 2?
  2. 我认为由于 c++ 会破坏符号名称,因此不会发生这种情况,并且链接器不会链接到库版本 2。所以我尝试了所有相同的方法,但我尝试使用 g++ 而不是 gcc 编译器。一切顺利,直到我尝试将应用程序链接到库,并且收到未解决的链接错误。不知道为什么。

附言抱歉,代码量很大。我试图说清楚。 谢谢

【问题讨论】:

  • 我正在结束这个问题。我理解它的第一部分,对于第二部分,我将创建新的更具体的问题

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


【解决方案1】:

是不是因为库导出了名称为“function”的符号,而应用程序尝试链接到相同的符号名称,这就是为什么链接器没有抱怨,而是链接到库版本 2 的原因?

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

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

是的,这个问题在 C++ 中不应该出现,因为名称修改。但是,只有当您的 应用程序代码库代码 都使用 C++ 或者以正确的方式桥接 C 和 C++ 代码时,这才是正确的。

很难说(没有完整列表)当您使用 g++ 时发生了什么,但从外观上看,您最终在 C++ 和 库代码中拥有 应用程序代码 /em> 仍在 C 中。如果是这种情况,您的 应用程序代码 现在将希望与损坏的 function 链接,而您的 库代码 仍导出未损坏的 function

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

nm main.o

... 看看它到底想要什么样的符号。如果你会得到这样的东西:

...
    U _Z3functionii
...

...而不是:

...
    U function
...

...那么就是这样。

要“修复”这个问题并使您的 C++应用程序代码链接到 库代码中未损坏的 function,您需要将函数原型声明为 extern "C" .

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-25
    • 1970-01-01
    • 2019-01-22
    • 1970-01-01
    • 2012-07-14
    • 1970-01-01
    相关资源
    最近更新 更多