Loading...
Searching...
No Matches
MetatomicLoader.cpp
Go to the documentation of this file.
1/*
2** This file is part of eOn.
3**
4** SPDX-License-Identifier: BSD-3-Clause
5*/
7
9
10#include <iostream>
11#include <vector>
12
13#ifndef _WIN32
14#include <dlfcn.h>
15#endif
16
17namespace eonc {
18
20 static MetatomicLoader loader;
21 return loader;
22}
23
25 if (m_loaded)
26 return true;
27
28#ifdef _WIN32
29 const char *candidates[] = {"metatomic_pot.dll", "libmetatomic_pot.dll",
30 nullptr};
31#elif defined(__APPLE__)
32 const char *candidates[] = {"libmetatomic_pot.dylib", "libmetatomic_pot.so",
33 nullptr};
34#else
35 const char *candidates[] = {"libmetatomic_pot.so", nullptr};
36#endif
37
38 // RTLD_GLOBAL without DEEPBIND so MetatomicPotential's Potential/PotRegistry
39 // symbols bind to the already-loaded host libeonclib (single registry).
40 auto open_mta = [](const char *name) -> dynlib::Handle {
41#if defined(__linux__)
42 return ::dlopen(name, RTLD_NOW | RTLD_GLOBAL);
43#elif defined(_WIN32)
44 return dynlib::open(name);
45#else
46 return ::dlopen(name, RTLD_NOW | RTLD_GLOBAL);
47#endif
48 };
49
50 for (const char **p = candidates; *p; ++p) {
51 m_handle = open_mta(*p);
52 if (m_handle)
53 break;
54 }
55 if (!m_handle) {
56 for (const auto &dir : PluginLoader::instance().search_paths()) {
57 for (const char **p = candidates; *p; ++p) {
58 std::string full = dir;
59 if (!full.empty() && full.back() != '/' && full.back() != '\\')
60 full += '/';
61 full += *p;
62 m_handle = open_mta(full.c_str());
63 if (m_handle)
64 break;
65 }
66 if (m_handle)
67 break;
68 }
69 }
70 if (!m_handle)
71 return false;
72
73 create = dynlib::loadSym<create_fn>(m_handle, "eon_mta_pot_create");
74 destroy = dynlib::loadSym<destroy_fn>(m_handle, "eon_mta_pot_destroy");
75 force = dynlib::loadSym<force_fn>(m_handle, "eon_mta_pot_force");
77 dynlib::loadSym<abi_version_fn>(m_handle, "eon_mta_abi_version");
78
79 if (!create || !destroy || !force || !abi_version) {
80 std::cerr << "[Metatomic] libmetatomic_pot loaded but missing C ABI "
81 "symbols\n";
83 m_handle = {};
84 create = nullptr;
85 destroy = nullptr;
86 force = nullptr;
87 abi_version = nullptr;
88 return false;
89 }
90 const int ver = abi_version();
91 if (ver != EON_MTA_ABI_VERSION) {
92 std::cerr << "[Metatomic] ABI version mismatch: library=" << ver
93 << " host=" << EON_MTA_ABI_VERSION << "\n";
95 m_handle = {};
96 create = nullptr;
97 destroy = nullptr;
98 force = nullptr;
99 abi_version = nullptr;
100 return false;
101 }
102 m_loaded = true;
103 return true;
104}
105
107
109 if (!try_load()) {
110 throw std::runtime_error(
111 "Metatomic potential requested but libmetatomic_pot.so not found or "
112 "ABI mismatch.\n"
113 "Build with -Dwith_metatomic=true and put the plugin on "
114 "LD_LIBRARY_PATH / EON_POTENTIALS_PATH / [Potential] potentials_path.");
115 }
116}
117
118} // namespace eonc
#define EON_MTA_ABI_VERSION
bool try_load()
Attempt (re)load if not yet successful. Safe after potentials_path inject.
static MetatomicLoader & instance()
MetatomicLoader(const MetatomicLoader &)=delete
dynlib::Handle m_handle
abi_version_fn abi_version
static PluginLoader & instance()
Thread-safe singleton accessor (Meyer's pattern).
void * Handle
Definition DynLib.h:60
Handle open(const char *name) noexcept
Definition DynLib.h:62
void close(Handle h) noexcept
Definition DynLib.h:77
Fn loadSym(Handle h, const char *name) noexcept
Load a symbol and cast to a function pointer type.
Definition DynLib.h:99
RAII resource manager for the ARTn C library with global synchronization.