编译.so动态库
最近在一个大项目分模块开发时,采用C++开发,各个模块开发好库之后,编译成为.so动态库。调用底层库时,只需要.so文件和对应头文件。
本文以test库为例说明:
文件包括:test.h test.cpp main.cpp
// test.h
#include <iostream>
using namespace std;
int add(int a, int b);
int subtract(int a, int b);
int multiply(int a, int b);
double divide(int a, int b);
// test.cpp
#include "test.h"
using namespace std;
int add(int a, int b){
return a+b;
}
int subtract(int a, int b){
return a-b;
}
int multiply(int a, int b){
return a*b;
}
double divide(int a, int b){
return a/1.0/b;
}
// main.cpp
#include <iostream>
#include "test.h"
using namespace std;
int main()
{
int a = 10, b = 20;
cout << add(a, b) << endl;
cout << subtract(a, b) << endl;
cout << multiply(a, b) << endl;
cout << divide(a, b) << endl;
return 0;
}
编译动态库:将test.h和test.cpp编译成libtest.so文件
g++ test.cpp -fPIC -shared -o libtest.so
mv *.so /home/wj/libso/
编译二进制可执行文件main
g++ main.cpp -L/home/wj/libso/ -ltest -o main
测试是否动态连接,如果列出libtest.so,那么应该是连接正常了
ldd main
-fPIC:作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。
-shared:该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件。
-L/home/wj/libso/:表示要连接的库在目录/home/wj/libso/
下
-ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称。对于test库,生成时前面加lib,即libtest.so;连接时,在前面加: -l,即:-ltest 。
正常链接动态库还需要将该动态库所在目录加到动态库的寻址目录下:
在个人配置目录下进行配置vim ~/.bashrc
,添加下面这一条命令:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/wj/libso
另:LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。