VIPRA Documentation
Loading...
Searching...
No Matches
module_loading.hpp
1#pragma once
2
3#include <filesystem>
4#include <functional>
5#include <memory>
6#include <stdexcept>
7#include <string>
8#include <type_traits>
9
10#include <dlfcn.h>
11
12#include "vipra/logging/logging.hpp"
13#include "vipra/modules.hpp"
14#include "vipra/special_modules/parameters.hpp"
15
16namespace VIPRA {
17
18template <typename module_t>
20 std::unique_ptr<std::remove_cvref_t<module_t>> module;
21 std::function<void(void*, Parameters&, VIPRA::Random::Engine&)> config_module;
22};
23
24template <typename module_t>
25inline auto load_module(std::string const& name, std::string const& installDir,
26 Modules::Type type) -> LoadedModule<module_t>
27{
28 using mod_t = std::remove_cvref_t<module_t>;
29 using make_module_t = mod_t* (*)();
30 using config_module_t = void (*)(void*, VIPRA::Parameters&, VIPRA::Random::Engine&);
31
32 std::string path;
33
34 if ( type == Modules::Type::PedInput || type == Modules::Type::MapInput )
35 path = installDir + "/input/lib" + name + ".so";
36 else
37 path = installDir + '/' + Modules::to_string(type) + "/lib" + name + ".so";
38
39 if ( ! std::filesystem::exists(path) ) {
40 VIPRA::Log::error("No Module {} at {}", name, path);
41 throw std::runtime_error("Module Not Found");
42 }
43
44 VIPRA::Log::debug("Loading Module: {} at {}", name, path);
45
46 void* module = dlopen(path.c_str(), RTLD_LAZY);
47
48 if ( module == nullptr ) {
49 std::cerr << "module not found at: " << path << '\n';
50 VIPRA::Log::error("dlopen failed: {}\n", dlerror());
51 throw std::runtime_error("Unable to load module");
52 }
53
54 // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast)
55 auto func = reinterpret_cast<make_module_t>(dlsym(module, "create_module"));
56 auto configFunc = reinterpret_cast<config_module_t>(dlsym(module, "setup_module"));
57 // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast)
58
59 if ( func == nullptr ) {
60 std::cerr << "create_module not found in: " << path << '\n';
61 throw std::runtime_error("Module Missing VIPRA_REGISTER_MODULE");
62 }
63
64 if ( configFunc == nullptr ) {
65 std::cerr << "setup_module not found in: " << path << '\n';
66 throw std::runtime_error("Module Missing VIPRA_REGISTER_MODULE");
67 }
68
69 VIPRA::Log::debug("Creating Module");
70
71 std::unique_ptr<mod_t> mod;
72 try {
73 mod.reset(func());
74 }
75 catch ( ... ) {
76 std::cerr << "Module not created, Error thrown in Module Construction\n";
77 throw std::runtime_error("Unable to create Module");
78 }
79
80 if ( mod.get() == nullptr ) {
81 std::cerr << "Module not created\n";
82 throw std::runtime_error("Unable to create Module");
83 }
84
85 VIPRA::Log::debug("Returning Module");
86
88 std::move(mod),
89 std::function<void(void*, Parameters&, VIPRA::Random::Engine&)>(configFunc)};
90}
91
92} // namespace VIPRA
static VIPRA_INLINE void error(fmt::format_string< param_ts... > message, param_ts &&... params)
Calls the provided Logger with Level DEBUG.
Definition logging.hpp:102
static VIPRA_INLINE void debug(fmt::format_string< param_ts... > message, param_ts &&... params)
Calls the provided Logger with Level DEBUG.
Definition logging.hpp:85
Definition parameters.hpp:20
Psuedo Random number engine.
Definition random.hpp:22
Definition module_loading.hpp:19