123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- #include "dynlib.h"
- #include "guard.h"
- #include "mutex.h"
- #include <util/generic/singleton.h>
- #include <util/generic/yexception.h>
- #ifdef _win32_
- #include "winint.h"
- #define DLLOPEN(path, flags) LoadLibrary(path)
- #define DLLCLOSE(hndl) FreeLibrary(hndl)
- #define DLLSYM(hndl, name) GetProcAddress(hndl, name)
- #else
- #include <dlfcn.h>
- #ifndef RTLD_GLOBAL
- #define RTLD_GLOBAL (0)
- #endif
- using HINSTANCE = void*;
- #define DLLOPEN(path, flags) dlopen(path, flags)
- #define DLLCLOSE(hndl) dlclose(hndl)
- #define DLLSYM(hndl, name) dlsym(hndl, name)
- #endif
- inline TString DLLERR() {
- #ifdef _unix_
- return dlerror();
- #endif
- #ifdef _win32_
- char* msg = 0;
- DWORD cnt = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, nullptr);
- if (!msg)
- return "DLLERR() unknown error";
- while (cnt && isspace(msg[cnt - 1]))
- --cnt;
- TString err(msg, 0, cnt);
- LocalFree(msg);
- return err;
- #endif
- }
- class TDynamicLibrary::TImpl {
- private:
- inline TImpl(const char* path, int flags)
- : Module(DLLOPEN(path, flags))
- , Unloadable(true)
- {
- (void)flags;
- if (!Module) {
- ythrow yexception() << DLLERR().data();
- }
- }
- class TCreateMutex: public TMutex {
- };
- public:
- static inline TImpl* SafeCreate(const char* path, int flags) {
- auto guard = Guard(*Singleton<TCreateMutex>());
- return new TImpl(path, flags);
- }
- inline ~TImpl() {
- if (Module && Unloadable) {
- DLLCLOSE(Module);
- }
- }
- inline void* SymOptional(const char* name) noexcept {
- return (void*)DLLSYM(Module, name);
- }
- inline void* Sym(const char* name) {
- void* symbol = SymOptional(name);
- if (symbol == nullptr) {
- ythrow yexception() << DLLERR().data();
- }
- return symbol;
- }
- inline void SetUnloadable(bool unloadable) {
- Unloadable = unloadable;
- }
- private:
- HINSTANCE Module;
- bool Unloadable;
- };
- TDynamicLibrary::TDynamicLibrary() noexcept {
- }
- TDynamicLibrary::TDynamicLibrary(const TString& path, int flags) {
- Open(path.data(), flags);
- }
- TDynamicLibrary::~TDynamicLibrary() = default;
- void TDynamicLibrary::Open(const char* path, int flags) {
- Impl_.Reset(TImpl::SafeCreate(path, flags));
- }
- void TDynamicLibrary::Close() noexcept {
- Impl_.Destroy();
- }
- void* TDynamicLibrary::SymOptional(const char* name) noexcept {
- if (!IsLoaded()) {
- return nullptr;
- }
- return Impl_->SymOptional(name);
- }
- void* TDynamicLibrary::Sym(const char* name) {
- if (!IsLoaded()) {
- ythrow yexception() << "library not loaded";
- }
- return Impl_->Sym(name);
- }
- bool TDynamicLibrary::IsLoaded() const noexcept {
- return (bool)Impl_.Get();
- }
- void TDynamicLibrary::SetUnloadable(bool unloadable) {
- Impl_->SetUnloadable(unloadable);
- }
|