Specs
Beautiful C++ Test Framework
Loading...
Searching...
No Matches
LibraryLoader.h
Go to the documentation of this file.
1#pragma once
2
3#include <Specs/API.h>
4#ifdef _WIN32
5 #include <Windows.h>
6#else
7 #include <dlfcn.h>
8#endif
9#include <collections.h>
10
11#include <filesystem>
12#include <string>
13#include <string_view>
14
15namespace SpecsCpp {
16
18 ISpecEnvironment* _globalSpecEnvironment = nullptr;
19
20#ifdef _WIN32
21 using LibraryPtr = HMODULE;
22#else
23 using LibraryPtr = void*;
24#endif
25
26 using LOAD_FUNCTION_SIGNATURE = ISpecGroup* (*)(ISpecEnvironment*);
27
28 static constexpr auto LOAD_FUNCTION_NAME = "SpecsCpp_Load";
29
30 collections_map<std::string, LibraryPtr> _loadedLibraries;
31
32 public:
33 LibraryLoader(ISpecEnvironment* globalSpecEnvironment)
34 : _globalSpecEnvironment(globalSpecEnvironment) {}
35
37
38 ISpecGroup* load(std::string_view libraryFilePath) {
39 if (!std::filesystem::exists(libraryFilePath))
40 throw std::runtime_error("File does not exist: " + std::string(libraryFilePath));
41
42#ifdef _WIN32
43 auto libraryHandle = LoadLibraryA(libraryFilePath.data());
44#else
45 auto libraryHandle = dlopen(libraryFilePath.data(), RTLD_LAZY);
46#endif
47
48 if (!libraryHandle)
49 throw std::runtime_error("Failed to load library: " + std::string(libraryFilePath));
50
51 auto loadFunctionAddress = GetProcAddress(libraryHandle, LOAD_FUNCTION_NAME);
52 if (!loadFunctionAddress)
53 throw std::runtime_error(
54 "Failed to get load function address: " + std::string(LOAD_FUNCTION_NAME)
55 );
56
57 auto loadFunction = reinterpret_cast<LOAD_FUNCTION_SIGNATURE>(loadFunctionAddress);
58
59 if (auto* group = loadFunction(_globalSpecEnvironment)) {
60 _loadedLibraries.emplace(libraryFilePath, libraryHandle);
61 return group;
62 } else {
63 FreeLibrary(libraryHandle);
64 throw std::runtime_error(
65 "Failed to load group from library: " + std::string(libraryFilePath)
66 );
67 }
68 }
69
70 bool unload(std::string_view libraryFilePath) {
71 if (auto it = _loadedLibraries.find(libraryFilePath.data());
72 it != _loadedLibraries.end()) {
73#ifdef _WIN32
74 FreeLibrary(it->second);
75#else
76 dlclose(it->second);
77#endif
78
79 _loadedLibraries.erase(it);
80 return true;
81 }
82 return false;
83 }
84
85 void unload_all() {
86 for (auto& [libraryFilePath, libraryHandle] : _loadedLibraries)
87 FreeLibrary(libraryHandle);
88 _loadedLibraries.clear();
89 }
90 };
91}
bool unload(std::string_view libraryFilePath)
LibraryLoader(ISpecEnvironment *globalSpecEnvironment)
ISpecGroup * load(std::string_view libraryFilePath)
Definition API.h:3