目录
- 一.前言
- 二.生成动态链接库
- 三.使用动态链接库
一.前言
这篇文章简单讨论一下Linux下如何使用gcc/g++生成和使用C++动态链接库(.so文件)。
二.生成动态链接库
先看下目录结构
然后看下代码
//demo.h
#ifndef DEMO_H
#define DEMO_H
#include<string>
class Demo
{
public:
Demo(void) = default;
~Demo(void) noexcept = default;
void Print(const std::string& msg);
};
#endif // !DEMO_H
//demo.cpp
#include"demo.h"
#include<iostream>
void Demo::Print(const std::string& msg)
{
std::cout << "msg:" << msg << std::endl;
}
很简单的代码,就是提供一个打印字符串的接口。
然后我们使用demo.h和demo.cpp来生成动态链接库。
执行命令g++ -shared -fPIC demo.cpp -o libdemo.so
生成动态链接库libdemo.so,注意动态链接库必须要包含lib前缀,另外我们知道Linux下动态链接库的后缀是.so。
g++ -shared -fPIC demo.cpp -o libdemo.so
命令中:
-shared表示生成动态链接库
-fPIC表示生成位置无关的代码,有些系统需要无论加载到什么位置都可以正常工作的位置无关代码
我们可以看到已经生成了动态链接库libdemo.so。
三.使用动态链接库
我们看一下怎么使用动态链接库,新建main.cpp来使用动态链接库。
先看下目录结构
然后看下代码
//main.cpp
#include<string>
#include"demo.h"
int main(int argc, char* argv[])
{
Demo demo;
std::string strMsg("main msg");
demo.Print(strMsg);
return 0;
}
其实就是很简单的代码。
然后执行命令g++ -o main main.cpp -L. -ldemo
使用main.cpp和libdemo.so生成可执行文件main。其中-L.指定要链接的库所在位置是当前目录,-ldemo指定要链接的库是libdemo.so。
我们可以看到已经生成了可执行文件main,我们试着执行一下。
发现报错,这个错误信息就是找不到动态链接库libdemo.so,我们使用ldd ./main
命令确认一下情况。
我们发现确实找不到动态链接库libdemo.so,这是因为系统不知道去哪里找libdemo.so,具体内容这篇文章里就不展开了,我们先使用命令export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/debian/code/demo
设置环境变量解决一下,这个目录是libdemo.so所在的位置。
我们可以看到这个时候就可以找到动态链接库libdemo.so了,而且可以正常执行。这个时候如果删除了动态链接库libdemo.so,main也会不可以正常执行了,这是动态链接库的特性,也就是所谓的动态链接。
需要注意的是,动态链接库的符号其实是需要导出的,g++编译的时候默认是设置-fvisibility=default选项,默认就会导出符号,但是如果开启了-fvisibility=hidden选项,我们想要导出某个符号的话,就需要设置属性__attribute__((visibility(“default”)))。
比如我们使用命令g++ -shared -fPIC ./demo.cpp -o libdemo.so -fvisibility=hidden
来生成动态库libdemo.so,那这个时候执行main就会报错的(其实这个时候如果重新编译生成main程序应该直接就会报错了,感兴趣的话可以试一下)。
这个报错的意思就是符号未定义。
我们修改一下声明代码就可以解决了。
看下代码
//demo.h
#ifndef DEMO_H
#define DEMO_H
#include<string>
class Demo
{
public:
Demo(void) = default;
~Demo(void) noexcept = default;
__attribute__((visibility("default"))) void Print(const std::string& msg);
};
#endif // !DEMO_H
然后我们还是使用命令g++ -shared -fPIC ./demo.cpp -o libdemo.so -fvisibility=hidden
来生成动态库libdemo.so。
这个时候main就可以正常执行了。