#include "polygon.hpp"
#include <iostream>
#include "soloador.hpp"
int main()
{
So::SoLoador<polygon> loador;
if (!loador.Load("./triangle.so"))
{
std::cout << "false" << std::endl;
}
auto ptr = loador.GetObject("create", "destroy");
if (ptr)
{
ptr->set_side_length(7);
std::cout << ptr->area() << std::endl;
}
return 0;
}
#ifndef SOLOADOR_H_
#define SOLOADOR_H_
#include <string>
#include <memory>
#include <dlfcn.h>
namespace So
{
template<typename Base>
class SoLoador
{
public:
SoLoador() : m_so(nullptr) {}
virtual ~SoLoador()
{
Unload();
}
bool Load(const std::string& so_path, int flag = RTLD_LAZY)
{
m_so = dlopen(so_path.c_str(), flag);
return m_so != nullptr;
}
void Unload()
{
if (m_so)
{
dlclose(m_so);
}
}
std::shared_ptr<Base> GetObject(const std::string& costructor, const std::string& destructor)
{
Base*(*create)() = (Base*(*)()) dlsym(m_so, costructor.c_str());
void(*destroy)(Base*) = (void(*)(Base*))dlsym(m_so, destructor.c_str());
if (nullptr == create || nullptr == destroy)
{
return nullptr;
}
std::shared_ptr<Base> obj(create(), destroy);
return obj;
}
private:
void* m_so;
};
} /* namespace So */
#endif /* SOLOADOR_H_ */
#ifndef POLYGON_HPP
#define POLYGON_HPP
class polygon
{
public:
polygon()
: side_length_(0)
{}
virtual ~polygon() {}
void set_side_length(double side_length)
{
side_length_ = side_length;
}
virtual double area() const = 0;
protected:
double side_length_;
};
#endif
#include "polygon.hpp"
#include <cmath>
class triangle: public polygon
{
public:
virtual double area() const
{
return side_length_ * side_length_ * std::sqrt(3) / 2;
}
};
// the class factories
extern "C" polygon* create()
{
return new triangle;
}
extern "C" void destroy(polygon *p)
{
delete p;
}
all:main so
main:
g++ -std=c++11 main.cpp -ldl -o main
so:
g++ -std=c++11 -shared -fpic triangle.cpp -o triangle.so