originals-tz
10/31/2019 - 1:20 AM

SoLoador

#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