一、创作背景
由于在多方压力逼迫下,强制我开始制造学术垃圾。借此机会便把所用到的C++在Linux下如何真正意义上借助dlopen使用动态库,从而方便利用语言的多态特性。
二、核心基类
为了不丢脸,还是不使用自己的项目代码进行演示,做个简单的demo吧。
偷懒用HPP文件,定义声明实现怼一起啦~
#ifndef SHAPE_HPP
#define SHAPE_HPP
#include <iostream>
class Shape
{
public:
Shape() {}
virtual double getArea() const = 0;
virtual double getPerim() const = 0;
virtual void print() = 0;
virtual void setShape(double edge1, double edge2, double angle) = 0;
virtual ~Shape() {}
static int count;
};
// the types of the class factories
typedef Shape *create_t();
typedef void destroy_t(Shape *);
void Shape::print()
{
std::cout << "Area: " << getArea()
<< " Perim: " << getPerim() << std::endl;
}
#endif
三、继承类的实现
图形类继承出一个平行四边形类
#ifndef PARALLELOGRAM_CPP
#define PARALLELOGRAM_CPP
#include "shape.hpp"
#include <cmath>
class Parallelogram : public Shape
{
protected:
double edge1;
double edge2;
double angle;
public:
Parallelogram(double edge1 = 0, double edge2 = 0, double angle = 0);
virtual void setShape(double edge1, double edge2, double angle);
virtual double getPerim() const;
virtual double getArea() const;
virtual void print();
};
Parallelogram::Parallelogram(double edge1, double edge2, double angle)
{
this->edge1 = edge1;
this->edge2 = edge2;
this->angle = angle;
}
void Parallelogram::setShape(double edge1, double edge2, double angle)
{
this->edge1 = edge1;
this->edge2 = edge2;
this->angle = angle;
}
double Parallelogram::getArea() const
{
return edge1 * edge2 * sin(angle);
}
double Parallelogram::getPerim() const
{
return 2 * (edge1 + edge2);
}
void Parallelogram::print()
{
std::cout << "Parallelogram: ";
Shape::print();
}
// the class factories
extern "C" Shape *create()
{
return new Parallelogram;
}
extern "C" void destroy(Shape *p)
{
delete p;
}
#endif // PARALLELOGRAM_CPP
四、康一康main函数
#include "shape.hpp"
#include <iostream>
#include <dlfcn.h>
#include <cmath>
int main()
{
void *handle = dlopen("./libparallelogram.so", RTLD_LAZY);
if (!handle)
{
std::cout << "Cannot open library" << std::endl;
return 1;
}
create_t *create = (create_t *)dlsym(handle, "create");
destroy_t *destroy = (destroy_t *)dlsym(handle, "destroy");
if (!create || !destroy)
{
std::cout << "Cannot find symbols" << std::endl;
return 1;
}
Shape *p = create();
p->setShape(1,2,M_PI/3);
p->print();
destroy(p);
dlclose(handle);
return 0;
}
五、编译运行
1)g++ parallelogram.cpp -fPIC -shared -o libparallelogram.so
2)g++ main.cpp -ldl
3)./a.out
六、结果展示
Parallelogram: Area: 1.73205 Perim: 6
七、总结分析
dlopen这个函数实际上如果不指定目录名./libparallelogram.so
这样子的话,会去本地的动态库目录内寻找。这时候就需要设置 LD_LIBRARY_PATH
环境变量。
此处带virtual关键字的函数,都是接口(interface) ,方便在装载不同动态库的时候,可实现同一接口但根据动态库不同来返回不同的信息内容(多态化)。