imate
C++/CUDA Reference
dynamic_loading.h
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: Copyright 2021, Siavash Ameli <sameli@berkeley.edu>
3  * SPDX-License-Identifier: BSD-3-Clause
4  * SPDX-FileType: SOURCE
5  *
6  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the license found in the LICENSE.txt file in the root
8  * directory of this source tree.
9  */
10 
11 
12 #ifndef _CUDA_DYNAMIC_LOADING_DYNAMIC_LOADING_H_
13 #define _CUDA_DYNAMIC_LOADING_DYNAMIC_LOADING_H_
14 
15 
16 // =======
17 // Headers
18 // =======
19 
20 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && \
21  !defined(__CYGWIN__)
22  #include <windows.h> // HMODULE, TEXT, LoadLibrary, GetProcAddress
23 #elif defined(__unix__) || defined(__unix) || \
24  (defined(__APPLE__) && defined(__MACH__))
25  #include <dlfcn.h> // dlopen, dlsym
26 #else
27  #error "Unknown compiler"
28 #endif
29 #include <stdexcept> // std::runtime_error
30 #include <sstream> // std::ostringstream
31 
32 
33 // ===============
34 // dynamic loading
35 // ===============
36 
78 
79 namespace dynamic_loading
80 {
81  // ==================
82  // get library handle (unix)
83  // ==================
84 
85  #if defined(__unix__) || defined(__unix) || \
86  (defined(__APPLE__) && defined(__MACH__))
96 
97  static void* get_library_handle_unix(const char* lib_name)
98  {
99  void* handle = dlopen(lib_name, RTLD_LAZY);
100 
101  if (!handle)
102  {
103  throw std::runtime_error(dlerror());
104  }
105 
106  return handle;
107  }
108  #endif
109 
110 
111  // ==================
112  // get library handle (windows)
113  // ==================
114 
115  #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && \
116  !defined(__CYGWIN__)
126 
127  static HMODULE get_library_handle_windows(const char* lib_name)
128  {
129  HMODULE handle = LoadLibrary(TEXT(lib_name));
130 
131  if (!handle)
132  {
133  std::ostringstream oss;
134  oss << "Cannot load the shared library '" << lib_name << "'." \
135  << std::endl;
136  std::string message = oss.str();
137  throw std::runtime_error(message);
138  }
139 
140  return handle;
141  }
142  #endif
143 
144 
145  // ===========
146  // load symbol
147  // ===========
148 
162 
163  template <typename Signature>
164  Signature load_symbol(
165  const char* lib_name,
166  const char* symbol_name)
167  {
168  #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && \
169  !defined(__CYGWIN__)
170 
171  HMODULE handle = get_library_handle_windows(lib_name);
172  FARPROC symbol = GetProcAddress(handle, symbol_name);
173 
174  if (symbol == NULL)
175  {
176  std::ostringstream oss;
177  oss << "The symbol '" << symbol << "' is failed to load " \
178  << "from the shared library '" << lib_name << "'." \
179  << std::endl;
180  std::string message = oss.str();
181  throw std::runtime_error(message);
182  }
183 
184  #elif defined(__unix__) || defined(__unix) || \
185  (defined(__APPLE__) && defined(__MACH__))
186 
187  void* handle = get_library_handle_unix(lib_name);
188  void* symbol = dlsym(handle, symbol_name);
189 
190  char *error = dlerror();
191  if (error != NULL)
192  {
193  throw std::runtime_error(dlerror());
194  }
195 
196  #else
197  #error "Unknown compiler"
198  #endif
199 
200 
201  return reinterpret_cast<Signature>(symbol);
202  }
203 
204 } // namespace dynamic_loading
205 
206 #endif // _CUDA_DYNAMIC_LOADING_DYNAMIC_LOADING_H_
Dynamic loading of shared libraries using dlopen tool.
Signature load_symbol(const char *lib_name, const char *symbol_name)
Loads a symbol within a library and returns a pointer to the symbol (function pointer).