动态库的生成
- 代码
// animal.hpp
#ifndef _ANIMAL_HPP
#define _ANIMAL_HPP
typedef unsigned int uint;
class animal
{
private:
uint m_number;
uint m_size;
public:
animal();
animal(uint num, uint size);
void setNum(uint num);
void setSize(uint size);
uint getNum();
uint getSize();
~animal();
};
#endif
// animal.cpp
#include"animal.hpp"
#include<iostream>
animal::animal():m_number(0),m_size(0)
{
std::cout << "this is no param construct functio for animal" << std::endl;
std::cout << "func = " << __func__ << " line = " << __LINE__ << std::endl;
std::cout << "m_number = " << m_number << " m_size = " << m_size << std::endl;
}
animal::animal(uint num, uint size):m_number(num),m_size(size)
{
std::cout << "this is a construct function with two param for animal" << std::endl;
std::cout << "func = " << __func__ << " line = " << __LINE__ << std::endl;
std::cout << "m_number = " << m_number << " m_size = " << m_size << std::endl;
}
animal::~animal()
{
m_number = 0;
m_size = 0;
}
void animal::setNum(uint num)
{
m_number = num;
}
void animal::setSize(uint size)
{
m_size = size;
}
uint animal::getNum()
{
return m_number;
}
uint animal::getSize()
{
return m_size;
}
//shared.hpp
#ifndef _SHARED_H__
#define _SHARED_H__
#include"animal.hpp"
#include<iostream>
class Fish : public animal
{
private:
std::string m_strType;
public:
/*
子类调用和继承父类的构造函数方法
1. 如果子类没有显示的调用父类的构造方法,那么会在创建子类的对象时,默认调用父类的默认无参构造函数
+ 此时是无关子类的构造函数,即不管子类是否定义了构造函数,还是显示定义了无参或者有参构造函数
+ 如果此时父类只定义了自己带参的构造函数,则会出现错误
2. 子类显示调用父类的构造函数,则调用对应的父类的构造函数
*/
Fish();
Fish(std::string str, uint num, uint size);
~Fish();
};
#endif
//shared.cpp
#include"shared.hpp"
Fish::Fish(std::string str, uint num, uint size):m_strType(str),animal(num,size)
{
std::cout << "the function with two paramr for Fish" << std::endl;
std::cout << "func = " << __func__ << " line = " << __LINE__ << std::endl;
std::cout << "str = " << str << " num = " << num << " size = " << size << std::endl;
}
Fish::Fish()
{
std::cout << "the function with no paramr for Fish" << std::endl;
std::cout << "func = " << __func__ << " line = " << __LINE__ << std::endl;
}
Fish::~Fish()
{
}
- 生成动态库
- g++ [file1.cpp] [file2.cpp] -fPIC -shared -o lib[dynamic_name].so
- g++ animal.cpp shared.cpp -fPIC -shared -o libdynamic.so
- 生成可执行程序
// main.cpp
#include<iostream>
#include"shared.hpp"
int main()
{
Fish salmon("salmon", 3, 10);
std::cout << "------------" << std::endl;
Fish whale;
}
- g++ [file3.cpp] -o [program_name] -L [path_dynamiclib] -l[dynamic_name]
- g++ main.cpp -o main -L . -ldynamic
- 执行程序
- 在执行动态库代码之前,最好检查一下该程序链接的动态库是否正确
- ldd [program_name]
- ldd main
linux-vdso.so.1 => (0x00007ffd46dd1000)
libdynamic.so => not found
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f5c82566000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f5c82350000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5c81f86000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5c81c7d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5c828e8000)
- 分析:
- 没有找到 libdynamic.so 动态库的路径,但是在编译的时候已经指明了动态库的路径是 ./
- 但是显示没找到
- 原因
- g++ -L ./ -llibname 仅仅只能指定好编译时所依赖的库
- 在程序运行时,会以以下的顺序中的文件夹去找所依赖的动态库
- 编译时目标代码时指定的动态库搜索路径;
- 环境变量 LD_LIBRARY_PATH 指定的动态库搜索路径
- 配置文件 /etc.ld.so.conf 中记录的动态库路径
- 默认的动态库搜索路径 /lib 和 /usr/lib
- 以上的路径中,如果没有 ./ 的话,就找不到当前需要的 libdynamic.so 动态库
- 解决方法:
- 在 LD_LIBRARY_PATH 中加入 ./ 路径
- export LD_LIBRARY_PATH=./
- 此时再执行 ldd 命令查看执行程序中 libdynamic.so 的路径是否找到
- 在编译时,使用命令 -Wl,-rpath,linkpath 直接指定当前程序的搜索路径
- g++ main.cpp -o main -L . -ldynamic -Wl,-rpath,./
- 再查看 ldd main
- 在 LD_LIBRARY_PATH 中加入 ./ 路径
- 补充
- 在大型项目中,推荐在makefile中使用方法2或者执行脚本命令将对应的库复制后者移动到默认的动态库搜索目录 /lib, /user/lib 文件夹中解决该问题,
- 原因在于,如果是需要修改临时环境变量或者修改配置文件 /etc.ld.so.conf,则可能在其他人或者另外一个环境中编译该文件运行时出现问题,产生额外的步骤