-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathFmuToolsRuntimeLinking.h
More file actions
131 lines (112 loc) · 4.48 KB
/
FmuToolsRuntimeLinking.h
File metadata and controls
131 lines (112 loc) · 4.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// =============================================================================
// fmu-forge
//
// Copyright (c) 2024 Project Chrono (projectchrono.org)
// Copyright (c) 2024 Digital Dynamics Lab, University of Parma, Italy
// Copyright (c) 2024 Simulation Based Engineering Lab, University of Wisconsin-Madison, USA
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution.
//
// =============================================================================
// Utilities for run-time linking of shared libraries
// =============================================================================
#ifndef FMUTOOLS_RUNTIMELINKING_H
#define FMUTOOLS_RUNTIMELINKING_H
#include <string>
#include <stdexcept>
#include <iostream>
#include "filesystem.hpp"
#if defined(_MSC_VER) || defined(_WIN32) || defined(__MINGW32__)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <Errhandlingapi.h>
#define DYNLIB_HANDLE HINSTANCE
#define get_function_ptr GetProcAddress
#include <system_error>
#include <memory>
#include <string>
#else
#include <dlfcn.h>
#include <limits.h>
#define DYNLIB_HANDLE void*
#define get_function_ptr dlsym
#endif
#include <iostream>
namespace fmu_forge {
/// @addtogroup fmu_forge
/// @{
/// Runtime/Dynamic linking of shared library.
/// @param dynlib_dir The directory where the shared library is located.
/// @param dynlib_name The name of the shared library.
DYNLIB_HANDLE RuntimeLinkLibrary(const std::string& dynlib_dir, const std::string& dynlib_name) {
#ifdef _WIN32
if (!SetDllDirectory(dynlib_dir.c_str())) {
std::cerr << "ERROR: Could not locate the DLL directory." << std::endl;
throw std::runtime_error("Could not locate the DLL directory.");
}
DYNLIB_HANDLE dynlib_handle = LoadLibrary(dynlib_name.c_str());
if (!dynlib_handle) {
DWORD error = ::GetLastError();
std::string message = std::system_category().message(error);
std::cerr << "ERROR: DLL directory is found, but cannot load the library: " << dynlib_name << std::endl;
std::cerr << "GetLastError returned: " << message << std::endl;
throw std::runtime_error("Could not load the library.");
}
return dynlib_handle;
#else
void* dlib = dlopen(dynlib_name.c_str(), RTLD_LAZY);
if (dlib == NULL) {
std::cerr << "ERROR: cannot load the shared object library: " << dynlib_name << std::endl;
std::string message = dlerror();
std::cerr << "dlerror returned: " << message << std::endl;
throw std::runtime_error("Could not load the library.");
}
return dlib;
#endif
}
/// Get the location of the shared library.
std::string GetLibraryLocation() {
fs::path library_path;
#ifdef _WIN32
HMODULE hModule = nullptr;
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCSTR)&GetLibraryLocation, &hModule)) {
char library_pathc[MAX_PATH];
DWORD result = GetModuleFileNameA(hModule, library_pathc, MAX_PATH);
if (result != 0) {
// std::cout << "The path of the FMU shared library is: " << library_pathc << std::endl;
library_path = std::string(library_pathc);
} else {
std::cerr << "Error getting the FMU shared library name. Error code: " << GetLastError() << std::endl;
}
} else {
std::cerr << "Error getting the FMU shared library handle. Error code: " << GetLastError() << std::endl;
}
#else
void* sym_ptr = nullptr;
// Check first if FMI2 then if FMI3
sym_ptr = dlsym(RTLD_DEFAULT, "fmi2DoStep");
if (sym_ptr == nullptr) {
sym_ptr = dlsym(RTLD_DEFAULT, "fmi3DoStep");
}
if (sym_ptr == nullptr) {
std::cerr << "Error: FmuToolsRuntimeLinking: cannot find either fmi2DoStep nor fmi3DoStep" << std::endl;
}
Dl_info dl_info;
if (dladdr(sym_ptr, &dl_info)) {
char library_pathc[PATH_MAX];
library_path = realpath(dl_info.dli_fname, library_pathc);
// std::cout << "The path of the FMU shared library is: " << library_pathc << std::endl;
library_path = std::string(library_pathc);
} else {
std::cerr << "Error getting the FMU shared library information." << std::endl;
}
#endif
fs::path library_folder = library_path.parent_path();
return library_folder.string();
}
/// @} fmu_forge
} // namespace fmu_forge
#endif