这篇文章简单讨论一下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。
我们可以看到已经生成了动态链接库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;
}
其实就是很简单的代码。
我们可以看到已经生成了可执行文件main,我们试着执行一下。
发现报错,这个错误信息就是找不到动态链接库libdemo.so,我们使用ldd ./main
命令确认一下情况。
我们可以看到这个时候就可以找到动态链接库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就可以正常执行了。
因篇幅问题不能全部显示,请点此查看更多更全内容