#pragma once #include #include #include #include #include using std::cout; using std::endl; template class DynamicLib { private: using produce_t = typename T::produce; using destruct_t = typename T::destruct; std::atomic counter; public: produce_t produce_method; destruct_t destruct_method; DynamicLib(const std::string& lib_path) : lib_path(lib_path), lib_object(nullptr) { load(); } typename T::lib_object* instance() { // TODO singleton, concurrency if (lib_object == nullptr) { lib_object = this->produce_method(); } return lib_object; } void load() { load_lib(); load_produce_func(); load_destruct_func(); } ~DynamicLib() { if (lib_object != nullptr) { destruct_method(lib_object); } } private: std::string lib_path; void *dynamic_lib; typename T::lib_object *lib_object; void load_lib() { dynamic_lib = dlopen(lib_path.c_str(), RTLD_LAZY); if (!dynamic_lib) { throw std::runtime_error(dlerror()); } dlerror(); } void load_produce_func() { produce_method = (produce_t) dlsym( dynamic_lib, T::produce_name.c_str() ); const char* dlsym_error = dlerror(); if (dlsym_error) { throw std::runtime_error(dlsym_error); } } void load_destruct_func() { destruct_method = (destruct_t) dlsym( dynamic_lib, T::destruct_name.c_str() ); const char *dlsym_error = dlerror(); if (dlsym_error) { throw std::runtime_error(dlsym_error); } } };