【问题标题】:How to use extern symbols in shared library in C如何在 C 中的共享库中使用外部符号
【发布时间】:2018-10-09 20:17:53
【问题描述】:

我正在尝试编译以下测试文件以创建共享库:

answer.c

#include <stdio.h>    
#include "add.h"    
extern int myvar();

int answer()
{    
    printf("\r\n myvar:%d \r\n", myvar());    
    setSummand(20);    
    return add(22);  // Will return 42 (=20+22)   
}

添加.c

#include <stdio.h>

int gSummand;    

void setSummand(int summand)
{    
    printf("1Library is initialized\n");    
    gSummand = summand;
}

int add(int summand)
{    
  return gSummand + summand;    
}

我想从 2 个文件“answer.c”“add.c”创建一个共享库,我正在使用以下命令:

gcc -c answer.c  -o answer.o
gcc -c add.c  -o add.o
gcc -shared add.o answer.o -o libtest.so

但是第三个命令给出以下错误:

answer.o:answer.c:(.text+0x9): undefined reference to `myvar'
answer.o:answer.c:(.text+0x9): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `myvar'
collect2: error: ld returned 1 exit status

如果我使用以下命令创建静态库而不是动态库,则相同的设置链接成功。因此,如果我尝试以下命令,我看不到任何错误:

ar rcs libtest.a add.o answer.o

想知道我是否在这里遗漏了什么。也想知道如何在共享库中使用外部符号。

【问题讨论】:

    标签: c gcc shared-libraries linker-errors extern


    【解决方案1】:

    ELF 共享库需要与位置无关。它们将被映射到可执行文件的地址空间中,该地址直到运行时才知道。这意味着没有绝对地址调用指令,例如可能用于调用myvar()

    在将源文件编译成目标文件时,您需要指定-fpic,这些目标文件将被放入共享库中。这告诉编译器生成不使用绝对地址等的代码,因此它可以与位置无关。

    使用此库的示例 main.c 文件:

    extern int answer(void);
    int myvar() { return 1; }
    int main(void) { return answer(); }
    

    没有-fpic的例子:

    [test]$ gcc -c add.c
    [test]$ gcc -c answer.c 
    [test]$ gcc -shared add.o answer.o -o libtest.so
    /usr/bin/ld: add.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
    /usr/bin/ld: answer.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
    /usr/bin/ld: final link failed: Nonrepresentable section on output
    collect2: error: ld returned 1 exit status
    

    -fpic 为例:

    [test]$ gcc -fpic -c add.c
    [test]$ gcc -fpic -c answer.c
    [test]$ gcc -shared add.o answer.o -o libtest.so
    [test]$ gcc main.c libtest.so
    [test]$ LD_LIBRARY_PATH=. ./a.out
    
     myvar:1 
    1Library is initialized
    

    【讨论】:

    • 你测试过这个吗?
    • 是的。当然,必须在某个地方定义 myvar() 才能生成一个工作程序。
    • 我尝试添加 -fPIC 但仍然看到相同的错误。让我知道以下标志是否正确: gcc -shared -fPIC add.o answer.o -o libtest.so answer.o:answer.c:(.text+0x9): undefined reference to myvar' answer.o:answer.c:(.text+0x9): relocation truncated to fit: R_X86_64_PC32 against undefined symbol myvar' collect2 : 错误: ld 返回 1 个退出状态
    • 您将标志放在错误的位置。我已经修改了我的答案以使其更清楚。
    • 我在编译目标文件时尝试使用该标志,但仍然遇到同样的问题。只需验证以下命令集是否正确: $ gcc -c -fPIC answer.c -o answer.o $ gcc -c -fPIC add.c -o add.o $ gcc -shared -fPIC add.o answer。 o -o libtest.so answer.o:answer.c:(.text+0x9): undefined reference to myvar' answer.o:answer.c:(.text+0x9): relocation truncated to fit: R_X86_64_PC32 against undefined symbol myvar' collect2: error: ld returned 1 exit status
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-18
    • 1970-01-01
    • 2020-08-20
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    相关资源
    最近更新 更多