Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
DLLSupport.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
8
9#include "Throw.h"
10#if qStroika_Foundation_Common_Platform_Windows
11#include "Platform/Windows/Exception.h"
12#endif
13
14#include "DLLSupport.h"
15
16// Comment this in to turn on aggressive noisy DbgTrace in this module
17//#define USE_NOISY_TRACE_IN_THIS_MODULE_ 1
18
19using namespace Stroika::Foundation;
20using namespace Stroika::Foundation::Execution;
21
23
24/*
25 ********************************************************************************
26 **************************** DLLSupport::DLLLoader *****************************
27 ********************************************************************************
28 */
29namespace {
30#if qStroika_Foundation_Common_Platform_POSIX
31 // CAN RETURN NULL
32 DLLHandle LoadDLL_ (const SDKChar* dllName, int flags)
33 {
34#if qTargetPlatformSDKUseswchar_t
35 return ::dlopen (Characters::SDK2Narrow (dllName).c_str (), flags);
36#else
37 return ::dlopen (dllName, flags);
38#endif
39 }
40#endif
41#if qStroika_Foundation_Common_Platform_Windows
42 // CAN RETURN NULL
43 DLLHandle LoadDLL_ (const SDKChar* dllName)
44 {
45 return ::LoadLibrary (dllName);
46 }
47#endif
48
49 void ThrowLoadErr_ ()
50 {
51 // @todo should do something to record the original DLL name
52#if qStroika_Foundation_Common_Platform_POSIX
53 // either main module or not found
54 const char* err = dlerror ();
55 if (err != nullptr) [[unlikely]] {
56 Execution::Throw (DLLException{err});
57 }
58#endif
59 Execution::ThrowSystemErrNo ();
60 }
61}
62
63DLLLoader::DLLLoader (const SDKChar* dllName)
64{
65#if USE_NOISY_TRACE_IN_THIS_MODULE_
66 DbgTrace (SDKSTR ("DLLLoader - loading DLL %s"), dllName);
67#endif
68 RequireNotNull (dllName);
69#if qStroika_Foundation_Common_Platform_POSIX
70 fModule_ = LoadDLL_ (dllName, RTLD_NOW);
71#elif qStroika_Foundation_Common_Platform_Windows
72 fModule_ = LoadDLL_ (dllName);
73#endif
74 if (fModule_ == nullptr) {
75 ThrowLoadErr_ ();
76 }
77}
78
79DLLLoader::DLLLoader (const SDKChar* dllName, const vector<filesystem::path>& searchPath)
80{
81#if USE_NOISY_TRACE_IN_THIS_MODULE_
82 DbgTrace (SDKSTR ("DLLLoader - loading DLL %s (with searchPath)"), dllName);
83#endif
84 RequireNotNull (dllName);
85#if qStroika_Foundation_Common_Platform_POSIX
86 fModule_ = LoadDLL_ (dllName, RTLD_NOW);
87#else
88 fModule_ = LoadDLL_ (dllName);
89#endif
90 if (fModule_ == nullptr) {
91 for (auto i = searchPath.begin (); i != searchPath.end (); ++i) {
92 filesystem::path modulePath = *i / dllName;
93#if qStroika_Foundation_Common_Platform_POSIX
94 fModule_ = LoadDLL_ (modulePath.c_str (), RTLD_NOW);
95#else
96 fModule_ = LoadDLL_ (modulePath.c_str ());
97#endif
98 if (fModule_ != nullptr) {
99 return;
100 }
101 }
102 }
103 if (fModule_ == nullptr) {
104 ThrowLoadErr_ ();
105 }
106}
107
108#if qStroika_Foundation_Common_Platform_POSIX
109DLLLoader::DLLLoader (const SDKChar* dllName, int flags)
110{
111#if USE_NOISY_TRACE_IN_THIS_MODULE_
112 DbgTrace (SDKSTR ("DLLLoader - loading DLL %s, flags=0x%x"), dllName, flags);
113#endif
114 RequireNotNull (dllName);
115 fModule_ = LoadDLL_ (dllName, RTLD_NOW);
116 if (fModule_ == nullptr) {
117 ThrowLoadErr_ ();
118 }
119}
120
121DLLLoader::DLLLoader (const SDKChar* dllName, const vector<filesystem::path>& searchPath, int flags)
122{
123#if USE_NOISY_TRACE_IN_THIS_MODULE_
124 DbgTrace (SDKSTR ("DLLLoader/3 - loading DLL %s, flags=0x%x"), dllName, flags);
125#endif
126#if qStroika_Foundation_Common_Platform_POSIX
127 fModule_ = LoadDLL_ (dllName, flags);
128#else
129 fModule_ = LoadDLL_ (dllName);
130#endif
131 if (fModule_ == nullptr) {
132 for (auto i = searchPath.begin (); i != searchPath.end (); ++i) {
133 filesystem::path modulePath = *i / dllName;
134#if qStroika_Foundation_Common_Platform_POSIX
135 fModule_ = LoadDLL_ (modulePath.c_str (), flags);
136#else
137 fModule_ = LoadDLL_ (modulePath.c_str ());
138#endif
139 if (fModule_ != nullptr) {
140 return;
141 }
142 }
143 }
144 if (fModule_ == nullptr) {
145 ThrowLoadErr_ ();
146 }
147}
148#endif
149
150DLLLoader::~DLLLoader ()
151{
152#if USE_NOISY_TRACE_IN_THIS_MODULE_
153 DbgTrace ("DLLLoader - unloading dll 0x%p", fModule_);
154#endif
155 AssertNotNull (fModule_);
156#if qStroika_Foundation_Common_Platform_Windows
157 ::FreeLibrary (fModule_);
158#else
159 if (::dlclose (fModule_) != 0) {
160 const char* err = ::dlerror ();
161 if (err != nullptr) [[unlikely]] {
162 Execution::Throw (DLLException{err});
163 }
164 }
165#endif
166}
#define AssertNotNull(p)
Definition Assertions.h:333
#define RequireNotNull(p)
Definition Assertions.h:347
#define DbgTrace
Definition Trace.h:309
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Definition Throw.inl:43