-
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.
Adds headers to handle loading shared libraries and their functions.
- Loading branch information
Showing
3 changed files
with
195 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#pragma once | ||
|
||
#if defined (__WIN32__) || defined(_WIN32) | ||
#include <windows.h> | ||
#define Dlsym(handle, symbol) GetProcAddress(handle, symbol) | ||
#elif defined(__linux__) | ||
#include <dlfcn.h> | ||
#define Dlsym(handle, symbol) dlsym(handle, symbol) | ||
#endif | ||
#include "get_os_error.hxx" | ||
|
||
#include <string> | ||
#include <stdexcept> | ||
|
||
template <typename func_t> | ||
class FuncLoader | ||
{ | ||
public: | ||
/** | ||
* @brief Loads a function from a shared library. | ||
* The shared library must be loaded before calling this. | ||
* | ||
* @param func_name [in] The name of the function to load from the shared library. | ||
* @param libname [in] The name of the shared library (used for messages only). | ||
* @param lib_handle [in] The handle for the shared lirbary loaded using the LibLoader. | ||
* @return The handle for the function to be used later in the program. | ||
* | ||
* @throws Runtime error if the load fails. | ||
*/ | ||
#if defined (__WIN32__) || defined(_WIN32) | ||
static func_t load(const char* func_name, const char* libname, HINSTANCE lib_handle) noexcept(false) | ||
#elif defined(__linux__) | ||
static func_t load(const char* func_name, const char* libname, void* lib_handle) noexcept(false) | ||
#endif | ||
{ | ||
func_t l_func = (func_t)Dlsym(lib_handle, func_name); | ||
if (l_func == nullptr) | ||
{ // Error handling for symbol resolution | ||
std::string message = std::string("Failed to load function: ") + std::string(func_name) + std::string(" from ") + | ||
std::string(libname) + std::string(" ("); | ||
|
||
std::string what_happened = get_os_error(); | ||
|
||
message += what_happened + std::string(")"); | ||
|
||
throw std::runtime_error(message.c_str()); | ||
} | ||
return l_func; | ||
} | ||
}; | ||
|
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,51 @@ | ||
#pragma once | ||
|
||
#include <string> | ||
|
||
#if defined (__WIN32__) || defined(_WIN32) | ||
#include <windows.h> | ||
#elif defined(__linux__) | ||
#include <dlfcn.h> | ||
#define Dlerror dlerror | ||
#endif | ||
|
||
inline std::string get_os_error() noexcept | ||
{ | ||
#if defined (__WIN32__) || defined(_WIN32) | ||
|
||
DWORD error_code = GetLastError(); | ||
|
||
// Buffer to store the error message | ||
TCHAR win_message[256]; | ||
|
||
// Call FormatMessage to convert the error code to a string | ||
DWORD result = FormatMessage( | ||
FORMAT_MESSAGE_FROM_SYSTEM, // Get message from system error codes | ||
NULL, // No source string to format | ||
error_code, // The error code to convert | ||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language | ||
win_message, // Buffer to receive the message | ||
sizeof(win_message) / sizeof(TCHAR) - 1, // Size of message buffer in TCHARs | ||
NULL // No additional formatting arguments | ||
); | ||
|
||
std::string what_happened; | ||
if (result) | ||
{ | ||
#ifdef UNICODE | ||
std::wstring tt = std::wstring(win_message); | ||
#else | ||
std::string tt = std::string(win_message); | ||
#endif | ||
|
||
what_happened = std::string(tt.begin(), tt.end()); | ||
} | ||
else | ||
// Handle potential formatting errors | ||
what_happened = std::string("Unknown error ") + std::to_string(error_code); | ||
#elif defined(__linux__) | ||
std::string what_happened = std::string(Dlerror()); | ||
#endif | ||
return what_happened; | ||
} | ||
|
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,93 @@ | ||
#pragma once | ||
|
||
#if defined (__WIN32__) || defined(_WIN32) | ||
#include <windows.h> | ||
#define Dlopen(name, flags) LoadLibraryA(name) | ||
#define Dlclose FreeLibrary | ||
#define Dlerror GetLastError | ||
#elif defined(__linux__) | ||
#include <dlfcn.h> | ||
#define Dlopen(name, flags) dlopen(name, flags) | ||
#define Dlclose dlclose | ||
#define Dlerror dlerror | ||
#endif | ||
|
||
#include "get_os_error.hxx" | ||
|
||
#include <stdexcept> | ||
#include <string> | ||
|
||
/** | ||
* @brief Cross-platform loader for dynamic libraries. | ||
*/ | ||
template <typename dtype_t> | ||
class LibLoader | ||
{ | ||
private: | ||
#if defined (__WIN32__) || defined(_WIN32) | ||
HMODULE p_lib_handle = nullptr; | ||
#elif defined(__linux__) | ||
void* p_lib_handle = nullptr; | ||
#endif | ||
public: | ||
|
||
/** | ||
* @brief Loads the dynamic library in memory. | ||
* | ||
* @param libname [in] The name of the library to load. For linux, "lib" is prepended to the name. | ||
* @param load_options [in] Ignored for Windows. | ||
* | ||
* @throws Runtime error if the load fails. | ||
*/ | ||
explicit LibLoader(const char* libname, const int load_options) noexcept(false) | ||
{ | ||
std::string local_libname{ libname }; | ||
#if defined(__linux__) | ||
local_libname = std::string("lib") + local_libname; | ||
#endif | ||
p_lib_handle = Dlopen(local_libname.c_str(), load_options); | ||
if (p_lib_handle == nullptr) | ||
{ // Error handling for loading the library | ||
std::string message = std::string("Failed to open library: ") + local_libname + std::string(" ("); | ||
|
||
std::string what_happened = get_os_error(); | ||
|
||
message += what_happened + std::string(")"); | ||
|
||
throw std::runtime_error(message.c_str()); | ||
} | ||
} | ||
|
||
/** | ||
* @brief Loads the dynamic library in memory. | ||
* | ||
* @param libname [in] The name of the library to load. For linux, "lib" is prepended to the name. | ||
* @param load_options [in] Ignored for Windows. | ||
* | ||
* @throws Runtime error if the load fails. | ||
*/ | ||
explicit LibLoader(const std::string& libname, const int load_options) noexcept(false) : | ||
LibLoader(libname.c_str(), load_options) | ||
{} | ||
|
||
/** | ||
* @brief Releases the handle to the library. | ||
*/ | ||
~DynLibLoader() noexcept | ||
{ | ||
Dlclose(p_lib_handle); | ||
} | ||
|
||
/** | ||
* @brief Returns the handle to the dynamic library. | ||
*/ | ||
#if defined (__WIN32__) || defined(_WIN32) | ||
HINSTANCE Handle() const | ||
#elif defined(__linux__) | ||
void* Handle() const | ||
#endif | ||
{ | ||
return p_lib_handle; | ||
} | ||
|
||
}; |