linux 动态链接库


Linux 动态链接库

最近由于一个偶然的机会,看到了一个作业里面需要用到动态链接库。回想起以前在PA的课上似乎有过这个知识,但是没有去尝试,所以抄了网上的一个demo

文件内容

这里有三个文件,foo.h,foo.c和main.c。foo.c是我们想要生成共享库,foo.h提供了共享库中的调用接口,然后main.c调用了共享库进行测试。

//foo.h
#ifndef foo_h__
#define foo_h__

extern void foo(void);

#endif  // foo_h__

//foo.c:
#include <stdio.h>

void foo(void)
{
    puts("Hello, I am a shared library");
}

//main.c:
#include <stdio.h>
#include "foo.h"

int main(void)
{
    puts("This is a shared library test...");
    foo();
    return 0;
}

生成共享库

在gcc编译时使用参数-shared可以生成共享库文件*.so。需要注意的是生成文件的文件名需要使用lib打头,比如生成libfoo.so在链接时就用-lfoo。

gcc -fPIC -shared -o libfoo.so foo.c

动态链接库的使用

通过-lfoo可以将库libfoo链接进程序中。-L.表示库在当前文件夹下,如果没有的话在链接时就会产生错误。 -Wl,-rpath=. 也表示库在当前目录下,这个是提供给程序运行时的,如果程序运行时在这个目录找不到共享库也会出错。linux默认的共享库放在/usr/lib等文件夹下,如果你把库放到那些文件夹下面就不需要指定-Wl,-rpath。之后程序就可以编译运行了。这里有一个非常坑的地方,就是-lfoo一定要放在main.c的后面,否则就会报错说函数未定义,感谢懿巨学长发现了这个bug,解决了我一个上午的疑惑。以后要记住把链接的参数写在最后面。

gcc -L. -Wl,-rpath=. -Wall -o test main.c -lfoo

运用

根据上面别人写的例子我写了一个小demo。项目地址
首先介绍一下项目结构, build下存放生成的共享库文件和二进制文件; lib目录放两个共享库,其中world.c依赖hello.c。然后helloworld.c依赖world.c

.
├── build
│   ├── helloworld
│   └── lib
│       ├── libhello.so
│       └── libworld.so
├── helloworld.c
├── lib
│   ├── hello.c
│   ├── hello.h
│   ├── world.c
│   └── world.h
└── Makefile

代码非常简单就是实现打印一行helloworld. 但是这里我们用到了两个共享库。

//hello.c
#include <stdio.h>

void hello()
{
	printf("hello ");
}

//world.c
#include "hello.h"
#include <stdio.h>
void world()
{
	hello();
	printf("world\n");
}

//helloworld.c
#include "lib/world.h"
int main()
{
	world();
}

依赖的顺序是helloworld->world->hello。首先编译hello.c生成共享库libhello.so,然后再编译world到libworld.so,最后把helloworld编译出来即可。这里需要注意的是world也需要加-Wl,-rpath的参数,否则运行时将找不到libhello.so。

# Makefile
helloworld: world helloworld.c
	mkdir -p build
	gcc -o ./build/helloworld -L./build/lib -Wl,-rpath=./build/lib helloworld.c -lworld

world: hello lib/world.c
	mkdir -p build/lib
	gcc -shared -o build/lib/libworld.so -L ./build/lib lib/world.c -Wl,-rpath=./build/lib -lhello -fPIC


hello: lib/hello.c
	mkdir -p build/lib
	gcc -shared -o build/lib/libhello.so lib/hello.c -fPIC

clean: 
	rm -rf build *.o *.so *.out helloworld

Author: 蒋璋
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source 蒋璋 !