Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
GlibDynamicLibraryLoader.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* GlibDynamicLibraryLoader.cc (C) 2000-2025 */
9/* */
10/* Dynamic library loader with Glib (uses gmodule). */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arccore/base/String.h"
15#include "arccore/base/PlatformUtils.h"
17#include "arccore/base/internal/IDynamicLibraryLoader.h"
18
19#include "gmodule.h"
20
21#include <iostream>
22#include <set>
23#include <vector>
24
25/*---------------------------------------------------------------------------*/
26/*---------------------------------------------------------------------------*/
27
28namespace Arcane
29{
30
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36class GlibDynamicLibrary
37: public IDynamicLibrary
38{
39 public:
40
41 GlibDynamicLibrary(GlibDynamicLibraryLoader* mng, GModule* gmodule)
42 : m_manager(mng)
43 , m_gmodule(gmodule)
44 {}
45
46 public:
47
48 void close() override;
49 void* getSymbolAddress(const String& symbol_name, bool* is_found) override;
50
51 private:
52
53 GlibDynamicLibraryLoader* m_manager = nullptr;
54 GModule* m_gmodule = nullptr;
55};
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59
63class GlibDynamicLibraryLoader
65{
66 public:
67
68 GlibDynamicLibraryLoader()
69 {
70 String s = platform::getEnvironmentVariable("ARCANE_VERBOSE_DYNAMICLIBRARY");
71 if (s == "1" || s == "true")
72 m_is_verbose = true;
73 }
74
75 void build() override {}
76
77 IDynamicLibrary* open(const String& directory, const String& name) override
78 {
79 IDynamicLibrary* dl = _tryOpen(directory, name);
80 if (!dl) {
81 // If not found, try with the '.dll' or '.dylib' extension because on
82 // windows or macos, some versions of GLIB automatically prefix the
83 // library name with 'lib' if it does not end with '.dll' or '.dylib'.
84#ifdef ARCCORE_OS_WIN32
85 dl = _tryOpen(directory, name + ".dll");
86#endif
87#ifdef ARCCORE_OS_MACOS
88 dl = _tryOpen(directory, "lib" + name + ".dylib");
89#endif
90 }
91 if (!dl) {
92 // If not found, try searching next to the binary
93 dl = _tryOpen(".", name);
94 }
95 if (!dl) {
96 // If not found, try searching next to the binary
97 // and with the dll or dylib extension
98#ifdef ARCCORE_OS_WIN32
99 dl = _tryOpen(".", name + ".dll");
100#endif
101#ifdef ARCCORE_OS_MACOS
102 dl = _tryOpen(".", "lib" + name + ".dylib");
103#endif
104 }
105 return dl;
106 }
107
108 IDynamicLibrary* _tryOpen(const String& directory, const String& name)
109 {
110 const gchar* gdirectory = reinterpret_cast<const gchar*>(directory.utf8().data());
111 const gchar* gname = reinterpret_cast<const gchar*>(name.utf8().data());
112 gchar* full_path = g_module_build_path(gdirectory, gname);
113 if (m_is_verbose) {
114 std::cout << "** Load Dynamic Library '" << full_path << "'...";
115 }
116 GModule* gmodule = g_module_open(full_path, GModuleFlags());
117 g_free(full_path);
118 if (m_is_verbose) {
119 if (!gmodule) {
120 std::cout << " NOT FOUND\n";
121 }
122 else {
123 std::cout << " OK\n";
124 }
125 }
126 if (!gmodule)
127 return nullptr;
128 auto lib = new GlibDynamicLibrary(this, gmodule);
129 m_opened_libraries.insert(lib);
130 return lib;
131 }
132
133 void closeLibraries() override
134 {
135 // This method will modify m_opened_libraries, so it must be copied first.
136 std::vector<GlibDynamicLibrary*> libs(m_opened_libraries.begin(), m_opened_libraries.end());
137 for (auto lib : libs) {
138 lib->close();
139 delete lib;
140 }
141 }
142
143 void removeInstance(GlibDynamicLibrary* lib)
144 {
145 auto iter = m_opened_libraries.find(lib);
146 if (iter != m_opened_libraries.end())
147 m_opened_libraries.erase(iter);
148 }
149
150 private:
151
152 bool m_is_verbose = false;
153 std::set<GlibDynamicLibrary*> m_opened_libraries;
154};
155
156/*---------------------------------------------------------------------------*/
157/*---------------------------------------------------------------------------*/
158
160close()
161{
162 if (!m_gmodule)
163 return;
164 bool is_ok = g_module_close(m_gmodule);
165 m_gmodule = 0;
166 if (!is_ok)
167 std::cerr << "WARNING: can not unload module\n";
168 m_manager->removeInstance(this);
169}
170
171/*---------------------------------------------------------------------------*/
172/*---------------------------------------------------------------------------*/
173
175getSymbolAddress(const String& symbol_name, bool* is_found)
176{
177 if (is_found)
178 *is_found = false;
179 if (!m_gmodule)
180 return nullptr;
181 const gchar* gname = reinterpret_cast<const gchar*>(symbol_name.utf8().data());
182 void* symbol_addr = nullptr;
183 bool r = ::g_module_symbol(m_gmodule, gname, &symbol_addr);
184 if (is_found)
185 (*is_found) = r;
186 return symbol_addr;
187}
188
189/*---------------------------------------------------------------------------*/
190/*---------------------------------------------------------------------------*/
191
192extern "C++" ARCCORE_BASE_EXPORT IDynamicLibraryLoader*
193createGlibDynamicLibraryLoader()
194{
196 idll->build();
197 return idll;
198}
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202namespace
203{
204 GlibDynamicLibraryLoader glib_dynamic_loader;
205 IDynamicLibraryLoader* global_default_loader = &glib_dynamic_loader;
206} // namespace
207
209{
210 return global_default_loader;
211}
212
213/*---------------------------------------------------------------------------*/
214/*---------------------------------------------------------------------------*/
215
216} // namespace Arcane
217
218/*---------------------------------------------------------------------------*/
219/*---------------------------------------------------------------------------*/
Types and functions associated with the classes ArrayView and ConstArrayView.
Interface for a dynamic library loader.
IDynamicLibrary * open(const String &directory, const String &name) override
Loads a dynamic library.
void closeLibraries() override
Closes all libraries opened via open().
void close() override
Closes the dynamic library.
void * getSymbolAddress(const String &symbol_name, bool *is_found) override
Returns the address of the symbol named symbol_name.
Interface of a dynamic library loader.
static IDynamicLibraryLoader * getDefault()
Service used for dynamically loading libraries.
Interface of a dynamic library.
ByteConstArrayView utf8() const
Returns the conversion of the instance into UTF-8 encoding.
Definition String.cc:277
String getEnvironmentVariable(const String &name)
Environment variable named name.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --