1 #pragma once 2 3 #include <dlfcn.h> 4 5 #include <stdexcept> 6 #include <string> 7 8 namespace mous { 9 10 using FnPluginType = PluginType (*)(void); 11 using FnPluginInfo = const PluginInfo* (*)(void); 12 using FnCreateObject = void* (*)(void); 13 using FnFreeObject = void (*)(void*); 14 15 class Plugin::Impl 16 { 17 public: 18 void* lib = nullptr; 19 FnPluginType GetPluginType = nullptr; 20 FnPluginInfo GetPluginInfo = nullptr; 21 FnCreateObject CreateObject = nullptr; 22 FnFreeObject FreeObject = nullptr; 23 PluginType type = PluginType::None; 24 Impl(const std::string & path)25 explicit Impl(const std::string& path) 26 { 27 std::string what; 28 29 lib = dlopen(path.c_str(), RTLD_LAZY | RTLD_GLOBAL); 30 if (!lib) { 31 goto RaiseException; 32 } 33 34 GetPluginType = reinterpret_cast<FnPluginType>(dlsym(lib, StrGetPluginType)); 35 if (!GetPluginType) { 36 goto CleanupAndRaise; 37 } 38 39 GetPluginInfo = reinterpret_cast<FnPluginInfo>(dlsym(lib, StrGetPluginInfo)); 40 if (!GetPluginInfo) { 41 goto CleanupAndRaise; 42 } 43 44 CreateObject = reinterpret_cast<FnCreateObject>(dlsym(lib, StrCreateObject)); 45 if (!CreateObject) { 46 goto CleanupAndRaise; 47 } 48 49 FreeObject = reinterpret_cast<FnFreeObject>(dlsym(lib, StrFreeObject)); 50 if (!CreateObject) { 51 goto CleanupAndRaise; 52 } 53 54 type = GetPluginType(); 55 return; 56 57 RaiseException: 58 what = dlerror(); 59 throw std::runtime_error(what); 60 61 CleanupAndRaise: 62 what = dlerror(); 63 dlclose(lib); 64 throw std::runtime_error(what); 65 } 66 ~Impl()67 ~Impl() { dlclose(lib); } 68 }; 69 } 70