PLaSK library

Loading...
Searching...
No Matches
loader.cpp
Go to the documentation of this file.
1/*
2 * This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3 * Copyright (c) 2022 Lodz University of Technology
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#include "loader.hpp"
15
16#include <iostream>
17#include "../../exceptions.hpp"
18
19#ifdef PLASK__UTILS_PLUGIN_WINAPI
20 #include "../minimal_windows.h"
21#else
22 #include <dlfcn.h>
23#endif
24
25 namespace plask {
26
27 DynamicLibrary::DynamicLibrary(const std::string& filename, unsigned flags)
28: handle(0) {
29 open(filename, flags);
30}
31
32 DynamicLibrary::DynamicLibrary(): handle(0) {}
33
34 DynamicLibrary::DynamicLibrary(DynamicLibrary&& to_move) noexcept
35 : handle(to_move.handle)
36#ifdef PLASK__UTILS_PLUGIN_WINAPI
37 , unload(to_move.unload)
38#endif
39{ to_move.handle = 0; }
40
41 DynamicLibrary::~DynamicLibrary() {
42 close();
43}
44
45#ifdef PLASK__UTILS_PLUGIN_WINAPI
46// Create a string with last error message, copied from http://www.codeproject.com/Tips/479880/GetLastError-as-std-string
47std::string GetLastErrorStr()
48{
49 DWORD error = GetLastError();
50 if (error)
51 {
52 LPVOID lpMsgBuf;
53 DWORD bufLen = FormatMessage(
54 FORMAT_MESSAGE_ALLOCATE_BUFFER |
55 FORMAT_MESSAGE_FROM_SYSTEM |
56 FORMAT_MESSAGE_IGNORE_INSERTS,
57 NULL,
58 error,
59 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
60 (LPTSTR) &lpMsgBuf,
61 0, NULL );
62 if (bufLen)
63 {
64 LPCSTR lpMsgStr = (LPCSTR)lpMsgBuf;
65 std::string result(lpMsgStr, lpMsgStr+bufLen);
66
67 LocalFree(lpMsgBuf);
68
69 return result;
70 }
71 }
72 return std::string();
73}
74#endif
75
76 void DynamicLibrary::open(const std::string &filename, unsigned flags) {
77 close(); // close if something is already opened
78#ifdef PLASK__UTILS_PLUGIN_WINAPI
79 //const int length = MultiByteToWideChar(CP_UTF8, 0, filename.data(), filename.size(), 0, 0);
80 //std::unique_ptr<wchar_t> output_buffer(new wchar_t [length]);
81 //MultiByteToWideChar(CP_UTF8, 0, filename.data(), filename.size(), output_buffer.get(), length);
82 //handle = LoadLibraryW(output_buffer->get());
83 handle = (handle_t)LoadLibraryA(filename.c_str());
84 if (!handle) {
85 throw plask::Exception("could not open dynamic library from file \"{0}\". {1}", filename, GetLastErrorStr());
86 }
87 unload = !(flags & DONT_CLOSE);
88#else
89 int mode = RTLD_NOW;
90 if (flags & DONT_CLOSE) mode |= RTLD_NODELETE;
91 handle = dlopen(filename.c_str(), mode);
92 if (!handle) {
93 throw plask::Exception("could not open dynamic library from file \"{0}\". {1}", filename, dlerror());
94 }
95#endif
96}
97
98 void DynamicLibrary::close() {
99 if (!handle) return;
100#ifdef PLASK__UTILS_PLUGIN_WINAPI
101 if (unload) {
102 if (!FreeLibrary((HINSTANCE)handle))
103 throw plask::Exception("can't close dynamic library: {0}", GetLastErrorStr());
104 }
105#else
106 if (dlclose(handle))
107 throw plask::Exception("can't close dynamic library: {0}", dlerror());
108#endif
109 handle = 0;
110}
111
112 void * DynamicLibrary::getSymbol(const std::string &symbol_name) const {
113 if (!handle)
114 throw plask::Exception("trying to get symbol from dynamic library which is not opened.");
115
116 return
117#ifdef PLASK__UTILS_PLUGIN_WINAPI
118 (void*) GetProcAddress((HINSTANCE)handle, symbol_name.c_str());
119#else
120 dlsym(handle, symbol_name.c_str());
121#endif
122}
123
124 void *DynamicLibrary::requireSymbol(const std::string &symbol_name) const {
125 void* result = getSymbol(symbol_name);
126 if (!result)
127 throw plask::Exception("there is no symbol \"{0}\" in dynamic library.", symbol_name);
128 return result;
129}
130
131 DynamicLibrary::handle_t DynamicLibrary::release() {
132 handle_t r = handle;
133 handle = 0;
134 return r;
135}
136
137 constexpr const char* DynamicLibrary::DEFAULT_EXTENSION;
138
139
140} // namespace plask