1 #include <opentracing/dynamic_load.h>
2 #include <opentracing/version.h>
6 namespace opentracing
{
7 BEGIN_OPENTRACING_ABI_NAMESPACE
8 // Returns the last Win32 error, in string format. Returns an empty string if
11 // Taken from https://stackoverflow.com/a/17387176/4447365
12 static std::string
GetLastErrorAsString() {
13 // Get the error message, if any.
14 DWORD errorMessageID
= ::GetLastError();
15 if (errorMessageID
== 0)
16 return std::string(); // No error message has been recorded
18 LPSTR messageBuffer
= nullptr;
19 size_t size
= FormatMessageA(
20 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
|
21 FORMAT_MESSAGE_IGNORE_INSERTS
,
22 NULL
, errorMessageID
, MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
23 (LPSTR
)&messageBuffer
, 0, NULL
);
25 std::string
message(messageBuffer
, size
);
28 LocalFree(messageBuffer
);
34 class DynamicLibraryHandleWindows
: public DynamicLibraryHandle
{
36 explicit DynamicLibraryHandleWindows(HINSTANCE handle
) : handle_
{handle
} {}
38 ~DynamicLibraryHandleWindows() override
{ FreeLibrary(handle_
); }
45 expected
<DynamicTracingLibraryHandle
> DynamicallyLoadTracingLibrary(
46 const char* shared_library
, std::string
& error_message
) noexcept
try {
47 const auto handle
= LoadLibrary(shared_library
);
48 if (handle
== nullptr) {
49 error_message
= "An error occurred: " + GetLastErrorAsString();
50 return make_unexpected(dynamic_load_failure_error
);
53 std::unique_ptr
<DynamicLibraryHandle
> dynamic_library_handle
{
54 new DynamicLibraryHandleWindows
{handle
}};
56 const auto make_tracer_factory
=
57 reinterpret_cast<OpenTracingMakeTracerFactoryType
**>(
58 GetProcAddress(handle
, "OpenTracingMakeTracerFactory"));
60 if (make_tracer_factory
== nullptr) {
62 "An error occurred while looking up for OpenTracingMakeTracerFactory "
64 GetLastErrorAsString();
65 return make_unexpected(dynamic_load_failure_error
);
68 if (*make_tracer_factory
== nullptr) {
70 "An error occurred while looking up for OpenTracingMakeTracerFactory. "
71 "It seems that it was set to nullptr.";
72 return make_unexpected(dynamic_load_failure_error
);
75 const void* error_category
= nullptr;
76 void* tracer_factory
= nullptr;
77 const auto rcode
= (*make_tracer_factory
)(
78 OPENTRACING_VERSION
, OPENTRACING_ABI_VERSION
, &error_category
,
79 static_cast<void*>(&error_message
), &tracer_factory
);
81 if (error_category
== nullptr) {
82 error_message
= "failed to construct a TracerFactory: unknown error code";
83 return make_unexpected(dynamic_load_failure_error
);
85 const auto error_code
= std::error_code
{
86 rcode
, *static_cast<const std::error_category
*>(error_category
)};
87 if (error_message
.empty()) {
88 error_message
= error_code
.message();
90 return make_unexpected(error_code
);
93 if (tracer_factory
== nullptr) {
95 "failed to construct a TracerFactory: `tracer_factory` is null";
96 return make_unexpected(dynamic_load_failure_error
);
99 return DynamicTracingLibraryHandle
{
100 std::unique_ptr
<const TracerFactory
>{
101 static_cast<TracerFactory
*>(tracer_factory
)},
102 std::move(dynamic_library_handle
)};
103 } catch (const std::bad_alloc
&) {
104 return make_unexpected(std::make_error_code(std::errc::not_enough_memory
));
106 END_OPENTRACING_ABI_NAMESPACE
107 } // namespace opentracing