Untitled
unknown
plain_text
2 years ago
3.2 kB
10
Indexable
// Factory.hpp
#include <string>
#include <memory>
#include <map>
#include <functional>
#include <dlfcn.h>
namespace RayTracer {
class Factory {
public:
Factory();
~Factory();
void loadAllPlugins();
void loadPlugin(
std::string const &name,
std::string const &path
);
void unloadPlugin(std::string const &name);
void unloadAllPlugins();
template<typename T, typename... Args>
std::unique_ptr<T> createPlugin(
std::string const &name,
Args... args
);
private:
std::map<std::string, void*> pluginHandles;
std::map<std::string, std::function<void*(Args...)>> pluginConstructors;
};
}
// Factory.cpp
#include "Factory.hpp"
RayTracer::Factory::Factory()
{
this->loadAllPlugins();
}
RayTracer::Factory::~Factory()
{
unloadAllPlugins();
}
void RayTracer::Factory::loadAllPlugins()
{
// Lights
this->loadPlugin("DirectionalLight", "./lights/DirectionalLight.so");
// Math
this->loadPlugin("Vector3D", "./math/Vector3D.so");
this->loadPlugin("Point3D", "./math/Point3D.so");
// Primitives
this->loadPlugin("Rectangle3D", "./primitives/Rectangle3D.so");
this->loadPlugin("Sphere", "./primitives/Sphere.so");
// Render
this->loadPlugin("Color", "./render/Color.so");
// View
this->loadPlugin("Camera", "./view/Camera.so");
this->loadPlugin("Ray", "./view/Ray.so");
}
void RayTracer::Factory::loadPlugin(
std::string const &name,
std::string const &path
)
{
void *pluginHandle = dlopen(path.c_str(), RTLD_NOW);
if (!pluginHandle) {
throw std::runtime_error("Failed to load plugin: " + name + " at path: " + path);
}
void *constructorPtr = dlsym(pluginHandle, ("create_" + name).c_str());
if (!constructorPtr) {
dlclose(pluginHandle);
throw std::runtime_error("Failed to find constructor for plugin: " + name);
}
pluginHandles[name] = pluginHandle;
pluginConstructors[name] = reinterpret_cast<std::function<void*(Args...)>>(constructorPtr);
}
void RayTracer::Factory::unloadPlugin(std::string const &name)
{
auto it = pluginHandles.find(name);
if (it != pluginHandles.end()) {
dlclose(it->second);
pluginHandles.erase(it);
pluginConstructors.erase(name);
}
}
void RayTracer::Factory::unloadAllPlugins()
{
for (auto &pair : pluginHandles) {
dlclose(pair.second);
}
pluginHandles.clear();
pluginConstructors.clear();
}
template<typename T, typename... Args>
std::unique_ptr<T> RayTracer::Factory::createPlugin(
std::string const &name,
Args... args
)
{
auto it = pluginConstructors.find(name);
if (it == pluginConstructors.end()) {
throw std::runtime_error("Plugin not found: " + name);
}
auto constructorFunc = it->second;
return std::unique_ptr<T>(reinterpret_cast<T*>(constructorFunc(args...)));
}
Editor is loading...