jaulib v1.3.6
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
native_lib.hpp
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2024 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24#pragma once
25
26#include <string>
27
28#include "jau/string_util.hpp"
29
31#include "jau/os/dyn_linker.hpp"
32
33namespace jau::os {
34
35 /** \addtogroup OSSup
36 *
37 * @{
38 */
39
40
41 /** Runtime libary dynamic library (RTLD) access. */
42 class NativeLibrary : public DynamicLookup {
43 private:
44 DynamicLinker& m_dynLink;
45
46 DynamicLinker::libhandle_t m_libraryHandle;
47
48 // May as well keep around the path to the library we opened
49 std::string m_libraryPath;
50
51 bool m_global;
52
53 // Native library path of the opened native libraryHandle, maybe null
54 std::string m_nativeLibraryPath;
55
56 static std::string getNativeLibPath(DynamicLinker& dl, DynamicLinker::libhandle_t libraryHandle,
57 const std::string& libraryPath, const std::string& symbolName) {
58 if( nullptr == libraryHandle ) {
59 return "";
60 } else {
61 const char *nlp = dl.lookupLibraryPathname(libraryHandle, symbolName);
62 if( nullptr != nlp ) {
63 return std::string(nlp);
64 } else {
65 return libraryPath;
66 }
67 }
68 }
69
70 // Private constructor to prevent arbitrary instances from floating around
71 NativeLibrary(DynamicLinker& dl, DynamicLinker::libhandle_t libraryHandle, const std::string& libraryPath, bool global, const std::string& symbolName)
72 : m_dynLink(dl), m_libraryHandle(libraryHandle), m_libraryPath(libraryPath), m_global(global),
73 m_nativeLibraryPath(getNativeLibPath(dl, libraryHandle, libraryPath, symbolName))
74 { }
75
76 public:
77
78 DynamicLinker::symhandle_t dynamicLookupFunction(const std::string& funcName) const noexcept override {
79 return m_dynLink.lookupSymbol(m_libraryHandle, funcName);
80 }
81
82 DynamicLinker::symhandle_t dynamicLookupFunctionGlobal(const std::string& funcName) const noexcept override {
83 return m_dynLink.lookupSymbolGlobal(funcName);
84 }
85
86 /** Returns the used DynamicLinker reference. */
87 DynamicLinker& dynamicLinker() const noexcept { return m_dynLink; }
88
89 /**
90 * Returns true if this instance is valid, i.e. native library successfully opened once but not necessarily isOpen() now.
91 * @see resolvedLibraryPath()
92 */
93 bool isValid() const noexcept { return m_nativeLibraryPath.size() > 0; }
94
95 /** Returns true if this instance isValid() and not close()'ed, otherwise false. */
96 bool isOpen() const noexcept { return nullptr != m_libraryHandle; }
97
98 /** Returns the native library handle if valid and not closed, otherwise nullptr. */
99 DynamicLinker::libhandle_t libraryHandle() const noexcept { return m_libraryHandle; }
100
101 /** Returns the path of the opened native library file. */
102 const std::string& libraryPath() const noexcept { return m_libraryPath; }
103
104 /**
105 * Returns the resolved native path of the opened native library, might be libraryPath() if not supported by OS.
106 *
107 * If this native library is not isValid(), method returns an empty string.
108 * @see isValid()
109 */
110 const std::string& resolvedLibraryPath() const noexcept { return m_nativeLibraryPath; }
111
112 /** Closes this native library. Further lookup operations are not allowed after calling this method. */
113 void close() noexcept {
114 DBG_PRINT("NativeLibrary.close(): closing %s", toString().c_str());
115 if ( nullptr != m_libraryHandle ) {
116 const DynamicLinker::libhandle_t handle = m_libraryHandle;
117 m_libraryHandle = nullptr;
118 m_dynLink.closeLibrary(handle);
119 DBG_PRINT("NativeLibrary.close(): Successfully closed %s", toString().c_str());
120 }
121 }
122
123 std::string toString() const noexcept {
124 if( isValid() ) {
125 return "NativeLibrary[path[given '" + m_libraryPath + "', native '"+m_nativeLibraryPath+"'], 0x" +
126 jau::to_hexstring(m_libraryHandle) + ", global " + std::to_string(m_global) + "]";
127 } else {
128 return "NativeLibrary[invalid, path[given '" + m_libraryPath + "'], 0x" +
129 jau::to_hexstring(m_libraryHandle) + ", global " + std::to_string(m_global) + "]";
130 }
131 }
132
133 /**
134 * Opens the given native library, assuming it has the same base name on all platforms.
135 *
136 * The {@code searchSystemPath} argument changes the behavior to
137 * either use the default system path or not at all.
138 *
139 * Assuming {@code searchSystemPath} is {@code true},
140 * the {@code searchSystemPathFirst} argument changes the behavior to first
141 * search the default system path rather than searching it last.
142 *
143 * @param libName library name, with or without prefix and suffix
144 * @param searchSystemPath if {@code true} library shall be searched in the system path <i>(default)</i>, otherwise {@code false}.
145 * @param searchSystemPathFirst if {@code true} system path shall be searched <i>first</i> <i>(default)</i>, rather than searching it last.
146 * if {@code searchSystemPath} is {@code false} this argument is ignored.
147 * @param global if {@code true} allows system wide access of the loaded library, otherwise access is restricted to the process.
148 * @return {@link NativeLibrary} instance, use isValid() to check whether the native library was loaded successful.
149 */
150 static NativeLibrary open(const std::string& libName,
151 const bool searchSystemPath,
152 const bool searchSystemPathFirst,
153 const bool global) noexcept {
154 return open(libName, searchSystemPath, searchSystemPathFirst, global, "");
155 }
156
157 /**
158 * Opens the given native library, assuming it has the same base name on all platforms.
159 *
160 * The {@code searchSystemPath} argument changes the behavior to
161 * either use the default system path or not at all.
162 *
163 * Assuming {@code searchSystemPath} is {@code true},
164 * the {@code searchSystemPathFirst} argument changes the behavior to first
165 * search the default system path rather than searching it last.
166 *
167 * @param libName library name, with or without prefix and suffix
168 * @param searchSystemPath if {@code true} library shall be searched in the system path <i>(default)</i>, otherwise {@code false}.
169 * @param searchSystemPathFirst if {@code true} system path shall be searched <i>first</i> <i>(default)</i>, rather than searching it last.
170 * if {@code searchSystemPath} is {@code false} this argument is ignored.
171 * @param loader {@link ClassLoader} to locate the library
172 * @param global if {@code true} allows system wide access of the loaded library, otherwise access is restricted to the process.
173 * @param symbolName optional symbol name for an OS which requires the symbol's address to retrieve the path of the containing library
174 * @return {@link NativeLibrary} instance, use isValid() to check whether the native library was loaded successful.
175 * @throws SecurityException if user is not granted access for the named library.
176 * @since 2.4.0
177 */
178 static NativeLibrary open(const std::string& libName,
179 const bool searchSystemPath,
180 const bool searchSystemPathFirst,
181 const bool global, const std::string& symbolName) noexcept {
182 std::vector<std::string> paths = DynamicLinker::enumerateLibraryPaths(libName, searchSystemPath, searchSystemPathFirst);
183
184 DynamicLinker& m_dynLink = DynamicLinker::get();
185
186 // Iterate down these and see which one if any we can actually find.
187 for (const std::string& path : paths ) {
188 DBG_PRINT("NativeLibrary.open(global %d): Trying to load %s", global, path.c_str());
190 if(global) {
191 res = m_dynLink.openLibraryGlobal(path);
192 } else {
193 res = m_dynLink.openLibraryLocal(path);
194 }
195 if ( nullptr != res ) {
196 NativeLibrary nl(m_dynLink, res, path, global, symbolName);
197 DBG_PRINT("NativeLibrary.open: Opened: %s", nl.toString().c_str());
198 return nl;
199 } else if( jau::environment::get().debug ) {
200 DBG_PRINT("NativeLibrary.open: Failed to open '%s', last error %s",
201 path.c_str(), m_dynLink.getLastError().c_str());
202 }
203 }
204 DBG_PRINT("NativeLibrary.open(global %d): Did not succeed in loading: '%s' within '%s'",
205 global, libName.c_str(), jau::to_string(paths).c_str());
206 return NativeLibrary(m_dynLink, nullptr, libName, global, symbolName);
207 }
208 };
209
210 /**@}*/
211
212} // namespace jau::os
213
static environment & get(const std::string &root_prefix_domain="jau") noexcept
Static singleton initialization of this project's environment with the given global root prefix_domai...
Low level secure dynamic linker access.
static DynamicLinker & get() noexcept
Returns static singleton instance of DynamicLinker.
static std::vector< std::string > enumerateLibraryPaths(const std::string &libName, bool searchSystemPath=false, bool searchSystemPathFirst=false) noexcept
Returns list of potential absolute library filenames.
void * symhandle_t
symbol handle within a library
void * libhandle_t
library handle
const char * lookupLibraryPathname(libhandle_t handle, const std::string &symbolName) noexcept
Interface callers may use ProcAddressHelper's reset helper method to install function pointers into a...
DynamicLinker & dynamicLinker() const noexcept
Returns the used DynamicLinker reference.
bool isValid() const noexcept
Returns true if this instance is valid, i.e.
void close() noexcept
Closes this native library.
DynamicLinker::symhandle_t dynamicLookupFunctionGlobal(const std::string &funcName) const noexcept override
Returns the function handle for function funcName gathered globally within all loaded libraries.
const std::string & resolvedLibraryPath() const noexcept
Returns the resolved native path of the opened native library, might be libraryPath() if not supporte...
const std::string & libraryPath() const noexcept
Returns the path of the opened native library file.
DynamicLinker::symhandle_t dynamicLookupFunction(const std::string &funcName) const noexcept override
Returns the function handle for function funcName gathered within the associated native library.
std::string toString() const noexcept
DynamicLinker::libhandle_t libraryHandle() const noexcept
Returns the native library handle if valid and not closed, otherwise nullptr.
bool isOpen() const noexcept
Returns true if this instance isValid() and not close()'ed, otherwise false.
static NativeLibrary open(const std::string &libName, const bool searchSystemPath, const bool searchSystemPathFirst, const bool global, const std::string &symbolName) noexcept
Opens the given native library, assuming it has the same base name on all platforms.
static NativeLibrary open(const std::string &libName, const bool searchSystemPath, const bool searchSystemPathFirst, const bool global) noexcept
Opens the given native library, assuming it has the same base name on all platforms.
#define DBG_PRINT(...)
Use for environment-variable environment::DEBUG conditional debug messages, prefix '[elapsed_time] De...
Definition debug.hpp:52
std::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
std::string to_hexstring(value_type const &v, const bool skipLeading0x=false) noexcept
Produce a lower-case hexadecimal string representation with leading 0x in MSB of the given pointer.
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2024 Gothel Software e.K.