forked from OpenTTD/OpenTTD
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Codechange: refactor the Windows-only DllLoader in a cross-platform L…
…ibraryLoader (OpenTTD#11751)
- Loading branch information
Showing
14 changed files
with
268 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/* | ||
* This file is part of OpenTTD. | ||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. | ||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
/** @file library_loader.h Functions/types related to loading libraries dynamically. */ | ||
|
||
#ifndef LIBRARY_LOADER_H | ||
#define LIBRARY_LOADER_H | ||
|
||
class LibraryLoader { | ||
public: | ||
/** | ||
* A function loaded from a library. | ||
* | ||
* Will automatically cast to the correct function pointer type on retrieval. | ||
*/ | ||
class Function { | ||
public: | ||
explicit Function(void *p) : p(p) {} | ||
|
||
template <typename T, typename = std::enable_if_t<std::is_function_v<T>>> | ||
operator T *() const | ||
{ | ||
return reinterpret_cast<T *>(this->p); | ||
} | ||
|
||
private: | ||
void *p; | ||
}; | ||
|
||
/** | ||
* Load a library with the given filename. | ||
*/ | ||
explicit LibraryLoader(const std::string &filename) | ||
{ | ||
this->handle = this->OpenLibrary(filename); | ||
} | ||
|
||
/** | ||
* Close the library. | ||
*/ | ||
~LibraryLoader() | ||
{ | ||
if (this->handle != nullptr) { | ||
this->CloseLibrary(); | ||
} | ||
} | ||
|
||
/** | ||
* Check whether an error occurred while loading the library or a function. | ||
* | ||
* @return Whether an error occurred. | ||
*/ | ||
bool HasError() | ||
{ | ||
return this->error.has_value(); | ||
} | ||
|
||
/** | ||
* Get the last error that occurred while loading the library or a function. | ||
* | ||
* @return The error message. | ||
*/ | ||
std::string GetLastError() | ||
{ | ||
return this->error.value_or("No error"); | ||
} | ||
|
||
/** | ||
* Get a function from a loaded library. | ||
* | ||
* @param symbol_name The name of the function to get. | ||
* @return The function. Check HasError() before using. | ||
*/ | ||
Function GetFunction(const std::string &symbol_name) | ||
{ | ||
if (this->error.has_value()) return Function(nullptr); | ||
return Function(this->GetSymbol(symbol_name)); | ||
} | ||
|
||
private: | ||
/** | ||
* Open the library with the given filename. | ||
* | ||
* Should set error if any error occurred. | ||
* | ||
* @param filename The filename of the library to open. | ||
*/ | ||
void *OpenLibrary(const std::string &filename); | ||
|
||
/** | ||
* Close the library. | ||
*/ | ||
void CloseLibrary(); | ||
|
||
/** | ||
* Get a symbol from the library. | ||
* | ||
* Should set error if any error occurred. | ||
* | ||
* @param symbol_name The name of the symbol to get. | ||
*/ | ||
void *GetSymbol(const std::string &symbol_name); | ||
|
||
std::optional<std::string> error = {}; ///< The last error that occurred, if set. | ||
void *handle = nullptr; ///< Handle to the library. | ||
}; | ||
|
||
#endif /* LIBRARY_LOADER_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ add_files( | |
) | ||
|
||
add_files( | ||
library_loader_unix.cpp | ||
unix.cpp | ||
CONDITION UNIX | ||
) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* This file is part of OpenTTD. | ||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. | ||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
/** @file library_loader_unix.cpp Implementation of the LibraryLoader for Linux / MacOS */ | ||
|
||
#include "../../stdafx.h" | ||
|
||
#include <dlfcn.h> | ||
|
||
#include "../../library_loader.h" | ||
|
||
#include "../../safeguards.h" | ||
|
||
/* Emscripten cannot dynamically load other files. */ | ||
#if defined(__EMSCRIPTEN__) | ||
|
||
void *LibraryLoader::OpenLibrary(const std::string &) | ||
{ | ||
this->error = "Dynamic loading is not supported on this platform."; | ||
return nullptr; | ||
} | ||
|
||
void LibraryLoader::CloseLibrary() | ||
{ | ||
} | ||
|
||
void *LibraryLoader::GetSymbol(const std::string &) | ||
{ | ||
this->error = "Dynamic loading is not supported on this platform."; | ||
return nullptr; | ||
} | ||
|
||
#else | ||
|
||
void *LibraryLoader::OpenLibrary(const std::string &filename) | ||
{ | ||
void *h = dlopen(filename.c_str(), RTLD_NOW | RTLD_LOCAL); | ||
if (h == nullptr) { | ||
this->error = dlerror(); | ||
} | ||
|
||
return h; | ||
} | ||
|
||
void LibraryLoader::CloseLibrary() | ||
{ | ||
dlclose(this->handle); | ||
} | ||
|
||
void *LibraryLoader::GetSymbol(const std::string &symbol_name) | ||
{ | ||
void *p = dlsym(this->handle, symbol_name.c_str()); | ||
if (p == nullptr) { | ||
this->error = dlerror(); | ||
} | ||
|
||
return p; | ||
} | ||
|
||
#endif /* __EMSCRIPTEN__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* This file is part of OpenTTD. | ||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. | ||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
/** @file library_loader_win.cpp Implementation of the LibraryLoader for Windows */ | ||
|
||
#include "../../stdafx.h" | ||
|
||
#include <windows.h> | ||
|
||
#include "../../library_loader.h" | ||
|
||
#include "../../safeguards.h" | ||
|
||
static std::string GetLoadError() | ||
{ | ||
auto error_code = GetLastError(); | ||
|
||
char buffer[512]; | ||
if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error_code, | ||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), nullptr) == 0) { | ||
return fmt::format("Unknown error {}", error_code); | ||
} | ||
|
||
return buffer; | ||
} | ||
|
||
void *LibraryLoader::OpenLibrary(const std::string &filename) | ||
{ | ||
void *h = ::LoadLibraryW(OTTD2FS(filename).c_str()); | ||
if (h == nullptr) { | ||
this->error = GetLoadError(); | ||
} | ||
|
||
return h; | ||
} | ||
|
||
void LibraryLoader::CloseLibrary() | ||
{ | ||
HMODULE handle = static_cast<HMODULE>(this->handle); | ||
|
||
::FreeLibrary(handle); | ||
} | ||
|
||
void *LibraryLoader::GetSymbol(const std::string &symbol_name) | ||
{ | ||
HMODULE handle = static_cast<HMODULE>(this->handle); | ||
|
||
void *p = reinterpret_cast<void *>(::GetProcAddress(handle, symbol_name.c_str())); | ||
if (p == nullptr) { | ||
this->error = GetLoadError(); | ||
} | ||
|
||
return p; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.